211 Commits

Author SHA1 Message Date
Vortrex
be29c02960 Remove duplicate locale strings 2023-03-07 21:05:08 -06:00
Vortrex
79e351cf8f Fix veh min rank + add who/when added 2023-03-07 21:01:23 -06:00
Vortrex
1cc54d4dd9 Set and remove password on start/reload (disabled) 2023-03-07 21:00:34 -06:00
Vortrex
b4aca0257f Save player payday 2023-03-07 20:59:53 -06:00
Vortrex
a11560b5b9 Add job and clan invite prompt types (unfinished) 2023-03-07 20:59:40 -06:00
Vortrex
0368ea3371 Check if payphone & player valid for desync fix 2023-03-07 20:59:23 -06:00
Vortrex
ea4cd87202 Fix send biz to client args 2023-03-07 20:58:40 -06:00
Vortrex
af2de3455e Remove set server password 2023-03-07 20:58:17 -06:00
Vortrex
785e506d69 Public job val + JSDoc + logging + invite cmd 2023-03-07 20:57:55 -06:00
Vortrex
eb30c616af Remove website/discord help categories (crashes) 2023-03-07 20:56:56 -06:00
Vortrex
a2eca84f52 Fix error when pay too low for tax + add eco cmds 2023-03-07 20:56:34 -06:00
Vortrex
a92fc14570 Save server chat type to database 2023-03-07 20:55:56 -06:00
Vortrex
063b2aab4f Allow manager cmd disable + add job/eco commands 2023-03-07 20:55:14 -06:00
Vortrex
242210bc9d Add prompt value to player data 2023-03-07 20:54:23 -06:00
Vortrex
9ab6bf2700 Check if global OOC enabled + add local OOC cmd 2023-03-07 20:54:09 -06:00
Vortrex
99da6df3ee Check for gun ban + show proper cost difference 2023-03-07 20:53:44 -06:00
Vortrex
bf88a14b23 Add new entries to job flags 2023-03-07 20:53:15 -06:00
Vortrex
72adf16515 Fix business labels 2023-03-07 20:52:26 -06:00
Vortrex
f6cb20b4ff Fix admin info category 2023-03-05 23:26:54 -06:00
Vortrex
9a06d7e7ba Mark inventory action tip seen 2023-03-05 23:26:34 -06:00
Vortrex
3de60247c6 Add job name to uniform list header 2023-03-05 23:26:19 -06:00
Vortrex
36c074ee3d Fix initial business label stuff 2023-03-05 23:26:05 -06:00
Vortrex
cbb820ec9f Woops wrong locale name 2023-03-05 23:25:56 -06:00
Vortrex
cf38abac7f Fix vehicle job/clan rank 2023-03-05 23:25:33 -06:00
Vortrex
f0d0384a41 Map change warning (unfinished) 2023-03-05 23:25:21 -06:00
Vortrex
37d485a7c3 Change word in local strings 2023-03-05 23:24:49 -06:00
Vortrex
1b04c60576 Chat type 2023-03-05 20:49:53 -06:00
Vortrex
0fcd38dd51 Update business.js 2023-03-05 20:49:47 -06:00
Vortrex
5c2320adea New locale strings 2023-03-05 20:48:25 -06:00
Vortrex
9713ecaf63 A few new commands 2023-03-05 20:48:16 -06:00
Vortrex
c1aaf8af53 Set inactive vehicle respawn to 60 minutes 2023-03-05 20:48:06 -06:00
Vortrex
5dbc93f38c Don't delete from database + fix job rank cmd 2023-03-05 20:47:29 -06:00
Vortrex
96586f6be0 More staff commands and fixes 2023-03-05 20:47:08 -06:00
Vortrex
4b63689f6e New locale strings 2023-03-05 20:46:55 -06:00
Vortrex
5d3119f051 Allow "all" payphone state set in net event 2023-03-05 20:46:39 -06:00
Vortrex
ec4a35d7bb Check for null vehicle 2023-03-05 20:46:22 -06:00
Vortrex
4e10158b29 Reset action tips command 2023-03-05 20:46:12 -06:00
Vortrex
b15964e763 Add job flag value util 2023-03-05 20:46:00 -06:00
Vortrex
0a9866ac9e Disable GUI prompts for now 2023-03-05 20:45:47 -06:00
Vortrex
7bb7775898 Admin-set chat type 2023-03-05 20:45:23 -06:00
Vortrex
c664e40d1e Don't delete from database 2023-03-05 20:45:09 -06:00
Vortrex
0d9388afa7 Net event rename 2023-03-05 20:44:45 -06:00
Vortrex
07cd95b861 Scene stuff 2023-03-05 20:44:34 -06:00
Vortrex
dbef2a2d5d Fix desynced payphones in timer 2023-03-05 20:44:13 -06:00
Vortrex
4cb1639461 Fix unoccupied veh util 2023-03-05 20:43:59 -06:00
Vortrex
f70021a4f2 Only give 20 default biz items 2023-03-05 20:43:42 -06:00
Vortrex
c54b0abf07 Use databaseId member when logging item buy 2023-03-04 23:46:04 -06:00
Vortrex
f843e43d66 Don't show nametags if in vehicle on Mafia 1 2023-03-04 23:45:42 -06:00
Vortrex
38e60a4837 Don't show labels if in vehicle on Mafia 1 2023-03-04 23:45:32 -06:00
Vortrex
90caff03a6 Add revision args to account hash/salts 2023-03-04 23:45:14 -06:00
Vortrex
eb7512f75c Add security config util 2023-03-04 23:45:00 -06:00
Vortrex
cdb67fa7e6 Reset payday after getting paid 2023-03-04 23:44:51 -06:00
Vortrex
d8b35d9aa9 Fix timestamp, remove extra strings in job route info 2023-03-04 23:44:38 -06:00
Vortrex
e0ae0793db Fix payphone database ID not being set 2023-03-04 23:44:18 -06:00
Vortrex
d87dfb0b05 Save next payday (in case of crash) 2023-03-04 23:43:56 -06:00
Vortrex
7193e349df Fix timestamp in veh info 2023-03-04 23:43:41 -06:00
Vortrex
7f6945f402 Check for null string 2023-03-04 23:43:33 -06:00
Vortrex
ef4c64f722 Check for empty string 2023-03-04 23:42:56 -06:00
Vortrex
992cc53dfd Job routes list and info commands 2023-03-04 08:36:48 -06:00
Vortrex
c6e1fb7f6d More JSDoc 2023-03-04 08:36:37 -06:00
Vortrex
16549d5042 Security config 2023-03-04 08:36:24 -06:00
Vortrex
e34d24033e Use british time format 2023-03-04 08:36:18 -06:00
Vortrex
738cd55e75 Add who/when added info to veh 2023-03-04 08:36:01 -06:00
Vortrex
1d0cbbd176 Use security config 2023-03-04 08:35:32 -06:00
Vortrex
d01a413ecc More JSDoc 2023-03-04 08:35:18 -06:00
Vortrex
72ae8aeead Load security config 2023-03-04 08:35:06 -06:00
Vortrex
6b3651f660 Check for job and rank on payday 2023-03-04 08:34:57 -06:00
Vortrex
77ef9dab35 New locale strings 2023-03-04 08:33:26 -06:00
Vortrex
802a489fee Fix wrong locale string in add key bind examples 2023-03-03 03:07:01 -06:00
Vortrex
f1d53734d3 Don't give arg to universal number locale string 2023-03-03 03:06:40 -06:00
Vortrex
1da6b82af5 Wrong del item util (fixes infinite veh fix item) 2023-03-03 03:06:23 -06:00
Vortrex
fef84bf75b Some fishing stuff (unfinished) 2023-03-03 03:05:48 -06:00
Vortrex
1782b6af2c Fix wrong command locale message 2023-03-03 03:05:35 -06:00
Vortrex
c61eee4197 Add new locale string 2023-03-03 03:05:18 -06:00
Vortrex
b695b3d9d0 Merge branch 'nightly' of https://github.com/VortrexFTW/v-roleplay into nightly 2023-03-03 01:32:50 -06:00
Vortrex
2ee939cc2c Merge branch 'master' into nightly 2023-03-03 01:32:19 -06:00
Vortrex
732940e56f Force add config files 2023-03-03 01:31:57 -06:00
Vortrex
19b433e7fb Remove config files (gitignore reset) 2023-03-03 01:28:45 -06:00
Vortrex
1d281256a1 Update .gitignore 2023-03-03 01:27:21 -06:00
Vortrex
e1137b728b Update .gitignore 2023-03-03 01:24:53 -06:00
Vortrex
908c5980e7 Set new payphone enabled 2023-03-03 00:51:31 -06:00
Vortrex
a8637692ee Number detective uniforms 2023-03-02 08:17:33 -06:00
Vortrex
e2f7b5403a Fix payphones 2023-03-02 08:17:20 -06:00
Vortrex
880de94677 Incoming damage multiplier network event handler 2023-03-02 08:17:07 -06:00
Vortrex
ef62513115 Woops wrong name 2023-03-02 08:16:52 -06:00
Vortrex
f2166cc804 Fix job uniforms not saving 2023-03-02 08:16:39 -06:00
Vortrex
b7cd14c654 Update incoming damage multiplier on drug use 2023-03-02 08:16:30 -06:00
Vortrex
c4a2f0aeda Use despawn functions + house labels 2023-03-02 08:16:12 -06:00
Vortrex
e27521761f Use new tax income field 2023-03-02 08:15:46 -06:00
Vortrex
0c936d4a8f Nearby businesses command 2023-03-02 08:15:35 -06:00
Vortrex
ea8efdc70a Add info files 2023-03-02 08:12:21 -06:00
Vortrex
23c8acae21 Woops wrong variable for chat message 2023-03-02 08:09:28 -06:00
Vortrex
868bb10091 Show job blips on edge when off of screen 2023-03-02 08:09:14 -06:00
Vortrex
453a946a1c Init job script on start 2023-03-02 08:08:52 -06:00
Vortrex
8a206bcaf8 Add weapon damage multiplier 2023-03-02 08:08:44 -06:00
Vortrex
588359ef27 Create ECONOMY.md 2023-03-02 05:15:26 -06:00
Vortrex
b27305e788 Don't log item move if dev server 2023-03-01 01:22:46 -06:00
Vortrex
f6ce6105e2 Biz nearby list cmd + buy log 2023-03-01 01:22:28 -06:00
Vortrex
ff2d416539 Remove economy config reload command 2023-03-01 01:20:32 -06:00
Vortrex
9f8d4cf034 Use server config for economy settings 2023-03-01 01:20:22 -06:00
Vortrex
3f925a4a44 Locate player command 2023-03-01 01:19:15 -06:00
Vortrex
b4d8acc07b Use server config for currency string 2023-03-01 01:18:56 -06:00
Vortrex
623434d70f More payphone commands & utils 2023-03-01 01:18:43 -06:00
Vortrex
f603d71062 Don't require args or player for staff flags list 2023-03-01 01:18:22 -06:00
Vortrex
f9d6f9eff3 Despawn all elements util + starting state 2023-03-01 01:18:06 -06:00
Vortrex
793b764469 Fix day/night cycle element spawning 2023-03-01 01:17:27 -06:00
Vortrex
3da2507cf7 Re-enabled day/night rule text 2023-03-01 01:17:14 -06:00
Vortrex
d7bbe1748e Dealership vehicle fix 2023-03-01 01:16:56 -06:00
Vortrex
e36d366f84 Add MafiaC train stations + fix vehicle names 2023-03-01 01:16:33 -06:00
Vortrex
b7eac224c5 Payphone state 2023-03-01 01:16:14 -06:00
Vortrex
67b8266a71 Add admin help category (needs finished) 2023-02-28 22:37:28 -06:00
Vortrex
f39697bf29 Commands is not a HouseData array lol 2023-02-28 22:37:10 -06:00
Vortrex
abea95a909 Use svr_main table for server economy settings 2023-02-28 22:36:57 -06:00
Vortrex
a9007338af Payphone + locate player commands 2023-02-28 22:36:42 -06:00
Vortrex
d55ae9ea6b Add world icons for businesses, house, and jobs 2023-02-28 22:36:20 -06:00
Vortrex
16a8014920 Move job objective icon image 2023-02-28 22:36:06 -06:00
Vortrex
cb54cc9aa5 Show debug logging in client console 2023-02-28 22:35:55 -06:00
Vortrex
b463c9f71f Remove economy.json (moved to database) 2023-02-28 22:35:43 -06:00
Vortrex
c8b2dca8de Add world icon images 2023-02-28 22:35:30 -06:00
Vortrex
4e0565eefe New locale strings 2023-02-28 22:35:10 -06:00
Vortrex
edcc063d8c Item type commands and output fixes 2023-02-26 20:08:49 -06:00
Vortrex
da578f40d9 Woops wrong game select 2023-02-26 20:08:27 -06:00
Vortrex
0900b0637a Save job rank + add JSDoc 2023-02-26 20:07:56 -06:00
Vortrex
84a55d76fb Fixes for some vehicle data ID issues 2023-02-26 20:07:43 -06:00
Vortrex
12f9a66349 Logging changes 2023-02-26 20:06:49 -06:00
Vortrex
081f78e53b Lower nametag height for MafiaC 2023-02-26 20:06:40 -06:00
Vortrex
272cfd9a3f Simple queueing script (needs finished) 2023-02-25 04:44:56 -06:00
Vortrex
d15ed19401 Add ammo items to Mafia 1 legal gun store + veh name fixes 2023-02-25 04:44:42 -06:00
Vortrex
57d274b334 Payphone state constants 2023-02-25 04:44:20 -06:00
Vortrex
1c5d2669fc Delete from table, don't update 2023-02-25 04:44:02 -06:00
Vortrex
896cb75591 Save veh positions + save payphones 2023-02-25 04:43:54 -06:00
Vortrex
920cfbd2ae Set payphone indexes in startup util 2023-02-25 04:43:33 -06:00
Vortrex
9205f07dbe Respawn vehicle on getveh, dont teleport 2023-02-25 04:43:18 -06:00
Vortrex
a388d94244 Payphone script fixes 2023-02-25 04:43:04 -06:00
Vortrex
0c7b25d0a8 Payphone net events 2023-02-25 04:42:39 -06:00
Vortrex
f4a2425fce Phone messaging functions 2023-02-25 04:42:29 -06:00
Vortrex
796072daab Send all payphones on spawn 2023-02-25 04:41:54 -06:00
Vortrex
085173d807 Add payphone distances to global config 2023-02-25 04:41:44 -06:00
Vortrex
11f034698b Add payphone commands to array 2023-02-25 04:41:29 -06:00
Vortrex
0762e4ac52 Add payphone data to client class 2023-02-25 04:41:11 -06:00
Vortrex
3fdc038242 Use payphone chat if on a call 2023-02-25 04:40:53 -06:00
Vortrex
9c9d242ae4 Init timers and payphone script 2023-02-25 04:39:37 -06:00
Vortrex
69317b3b1f Add client timers script 2023-02-25 04:39:27 -06:00
Vortrex
e14d7170aa Add payphone client script 2023-02-25 04:39:00 -06:00
Vortrex
d7b911004b Payphone net events 2023-02-25 04:38:51 -06:00
Vortrex
14fe451c83 Job route location check 2023-02-25 04:38:44 -06:00
Vortrex
9c86ad0e2c Process payphone and job route location 2023-02-25 04:38:01 -06:00
Vortrex
a8802c0c7e Add payphone array 2023-02-25 04:37:45 -06:00
Vortrex
c4fc123d75 Organize + add new files 2023-02-25 04:37:37 -06:00
Vortrex
64a9280fe6 New locale strings 2023-02-25 04:37:22 -06:00
Vortrex
b11510005a Add payphone sound files 2023-02-25 04:36:58 -06:00
Vortrex
85b934064e Move logo to lower left 2023-02-23 01:17:44 -06:00
Vortrex
542d1384db Use utils for vehicle delete/despawn 2023-02-23 01:17:33 -06:00
Vortrex
93e48df39a Add passive income to business till if players are on 2023-02-23 01:17:16 -06:00
Vortrex
52e8d6c1db Payphone array is camel case 2023-02-23 01:16:40 -06:00
Vortrex
b632e1d26b Add vehicle occupants native wrap 2023-02-23 01:16:16 -06:00
Vortrex
efea8a015f Add job pay 2023-02-23 01:16:05 -06:00
Vortrex
a0d03a0aab Check for clan before clan chat 2023-02-23 01:15:49 -06:00
Vortrex
c225c4d130 Move local player vehicle control state to vehicle.js 2023-02-23 01:15:41 -06:00
Vortrex
8532aa74ca Fix remove player from veh 2023-02-23 01:15:29 -06:00
Vortrex
0f788068c1 Job route indicator 2023-02-23 01:13:48 -06:00
Vortrex
d07a890a10 Process job route location rendering 2023-02-23 01:13:39 -06:00
Vortrex
b746970b9f Move fade camera func to camera.js 2023-02-23 01:13:24 -06:00
Vortrex
64a3d2daf8 Add objective icon to meta.xml 2023-02-23 01:13:12 -06:00
Vortrex
56ce5b7846 Make objective icon white 2023-02-23 01:13:04 -06:00
Vortrex
d940d6033e Don't respawn vehicle on job route finish 2023-02-22 16:45:43 -06:00
Vortrex
49026b7faf Only set job vehicle colour if supported 2023-02-22 16:27:26 -06:00
Vortrex
b9f47539a8 Fixes for interior scene change 2023-02-22 16:27:13 -06:00
Vortrex
51194882c1 Fixes for interior scene change 2023-02-22 16:26:59 -06:00
Vortrex
998dbf33f8 Load payphone script and data 2023-02-22 16:26:47 -06:00
Vortrex
dff8b8b8db Payphone array 2023-02-22 16:26:00 -06:00
Vortrex
21b2429536 Add ManagePayphones staff permission 2023-02-22 16:25:53 -06:00
Vortrex
520164269b Add payphone script and commands 2023-02-22 16:24:56 -06:00
Vortrex
44cbdc07ac Fix duplicate vehicle spawning 2023-02-22 05:27:03 -06:00
Vortrex
ac397a9011 Rename main world scene 2023-02-22 05:26:53 -06:00
Vortrex
8e11b9337b Disable day/night cycle on Mafia 1 for now 2023-02-22 05:26:42 -06:00
Vortrex
d2335e7bec Woops removed stuff from wrong native file 2023-02-22 05:26:07 -06:00
Vortrex
b39abaab6c Use util for main world scene 2023-02-22 05:25:51 -06:00
Vortrex
150d3f10b0 Add job rank command 2023-02-22 05:25:40 -06:00
Vortrex
810acd8036 Send correct job type 2023-02-22 05:25:28 -06:00
Vortrex
339ec0808c Add job rank command 2023-02-22 05:25:17 -06:00
Vortrex
d1e9b6f08b Fix clan owner command 2023-02-22 05:24:34 -06:00
Vortrex
f6d1ee189c Convert scoreboard key to int 2023-02-22 05:24:20 -06:00
Vortrex
549f8a3c59 Convert enter property key to int 2023-02-22 05:24:07 -06:00
Vortrex
e8d7b9312a Fix nametags for Mafia 1 2023-02-22 05:23:54 -06:00
Vortrex
fcdf8542d6 Fix job type 2023-02-22 05:23:46 -06:00
Vortrex
5401bb33c2 New string 2023-02-22 05:23:31 -06:00
Vortrex
7b9a41f8d1 Scoreboard command 2023-02-21 20:28:46 -06:00
Vortrex
a5008bdbf5 Use job index, not database ID 2023-02-21 20:28:37 -06:00
Vortrex
e3a0b27c4e Scoreboard error checking 2023-02-21 20:28:27 -06:00
Vortrex
697ccd860f Use label distance, not pickup distance 2023-02-21 20:28:17 -06:00
Vortrex
9536ed9aa9 Comment unfinished stuff 2023-02-21 20:28:06 -06:00
Vortrex
5ebbe17920 Fix biz label not showing buy info 2023-02-21 19:49:28 -06:00
Vortrex
d8dde07845 Change HUD money colour to white (will add more to HUD) 2023-02-21 19:49:13 -06:00
Vortrex
9c16ceeb3a Fix job label rendering 2023-02-21 19:49:00 -06:00
Vortrex
faf4a1569c Nametag fixes 2023-02-21 19:48:49 -06:00
Vortrex
d70a8d451a Make scoreboard key re-bindable 2023-02-21 19:48:38 -06:00
Vortrex
a0477b10fe Woops wrong variable name for chat message 2023-02-21 19:44:28 -06:00
Vortrex
700e98768e Make default chat global (will add config for this later) 2023-02-21 19:44:18 -06:00
Vortrex
adb8975c6a Colour for client code execute 2023-02-21 19:44:01 -06:00
Vortrex
c76459e777 Move setup all event handlers to native files 2023-02-21 19:43:51 -06:00
Vortrex
961670687f Move locked state to bottom 2023-02-21 19:43:31 -06:00
Vortrex
eaa0f3a563 Enable world labels on Mafia 1 2023-02-21 19:43:23 -06:00
Vortrex
4dcbcf5658 Wtf extra character inserted 2023-02-21 14:42:23 -06:00
Vortrex
77fbc48f4e Fix names and enable nametags on Mafia 2023-02-21 14:40:01 -06:00
Vortrex
b4ac02f9ec Remove all async/await stuff 2023-02-21 14:39:45 -06:00
Vortrex
1cb02b9ab1 Update database.sql 2023-02-20 21:36:38 -06:00
Vortrex
b42f98917d Update name 2023-02-18 15:43:36 -06:00
Vortrex
62a4581c55 Update README.md 2023-02-18 14:20:37 -06:00
Vortrex
0607057f3f Update README.md 2023-02-18 14:18:46 -06:00
Vortrex
ab4cd7a212 Add features list 2023-02-18 14:17:57 -06:00
98 changed files with 5721 additions and 2447 deletions

1
.gitignore vendored
View File

@@ -1,3 +1,4 @@
.vs/
.git/
*.code-workspace
config

41
ECONOMY.md Normal file
View File

@@ -0,0 +1,41 @@
# Economy Information
### Basic Information
Each server has it's own independent economy with simulated inflation and is designed to slowly self-repair over time, assuming nothing is affecting it too heavily.
---
### Asset Ownership
Any player or clan is allowed to own as many businesses, vehicles, and houses as they want. However, it should be noted that the more you own, the more upkeep (via taxes, insurance, etc) is required. Failure to maintain this upkeep for too long will automatically force you to lose the unmaintained assets. Vehicle owners can park their car anywhere (subject to IC parking laws), store items in the trunk or dash compartment, give anybody access, and set the price if they want to make it available to buy, and more. Business owners can stock their store with any item they want, set what prices they want for any item for sale, close/open the business, keep a stock of items in the business's storage, force people to pay a fee to enter, and more. House owners can store items in their house, purchase a safe, decorate with furniture, give anybody access, and more.
---
### Ordering Items for a Business
Ordering items is simple: just use the /bizorder command.
You'll need to specify which item you want to order and how many.
Remember, the prices will vary depending on certain circumstances.
The formula is as follows:
> Base price * server inflation * demand * risk * amount
**Here's a breakdown on how the above formula works:**
* First, each item has a base price. This value will never change.
* Next, the base price is multiplied by the server's current inflation value. When the servers were first opened, the inflation value is 100%, which means no inflation. Everything cost 100% of it's calculated price. However, the inflation will slowly increase over time, simulating realistic economy inflation.
* Next, the inflated price is then multiplied by the demand factor, which is determined by how much demand there is for the item you want. Every 10 of the item ordered increases the demand value by 10%, and this will slowly go back down over time. If another business just ordered 100 of the item you want, the demand has forced the item's order price to increase by 100%, which means it's now double the original price. This simulates the things involved with increased demand, such as the extra manufacturing and shipping needed to get this item imported to your business.
* Next, the cost is multiplied by a risk value. This value never changes, and varies depending on the item. For illegal items, the risk value will be lower for less-risky items and higher as they get worse. For example, a shotgun versus an AK-47 have different risk levels, as an AK-47 is a far deadlier and a harder to get weapon, and is more difficult to conceal through customs. This simulates the "risk" of ordering items like these. For legal items, there is no risk so the risk price won't increase for those.
* Finally, the order cost is multiplied by the amount you want to order.
**An example of this formula in action is below ... shown for an order for 10 AK-47's with no inflation**
*The demand is increased by 10% since you're ordering 10 of them. 1 = 100% of the normal cost, 1.1 = 110%, and so on.*
> Base price $1000
> x inflation 1 = $1000
> x demand 1.1 = $1100
> x risk 5 = $5500
> x amount 10 = $55000
So as you can see, the total cost to order 10 AK-47's in this scenario is $55,000. Remember, an AK-47 is a deadly and uncommon weapon (and highly illegal!) so it's a very risky and costly thing to do business with.

View File

@@ -1,7 +1,7 @@
# Vortrex's Roleplay Resource
### Description
This is Vortrex's Roleplay Resource
This is Vortrex's Roleplay Resource. Originally created for [GTA Connected](https://gtaconnected.com/) but support for other multiplayer mods coming soon!
### Supported Games and Multiplayer Mods
* GTA III (on [GTA Connected](https://gtaconnected.com/))
@@ -9,6 +9,29 @@ This is Vortrex's Roleplay Resource
* GTA SA (on [GTA Connected](https://gtaconnected.com/))
* GTA IV (on [GTA Connected](https://gtaconnected.com/))
* Mafia: The City of Lost Heaven (on [Mafia Connected](https://mafiaconnected.com/))
* **(Coming Soon!)** GTA V (on [RAGEMP](https://rage.mp/))
* **(Coming Soon!)** Mafia Definitive Edition (on MafiaMP)
### Features
*Some features may be disabled on specific multiplayer mods depending on functionality*
* Works on multiple server instances sharing the same database
* Jobs operate as factions but leader can make ranks "public" so anybody can use those if enabled.
* Clans with custom ranks, permissions, pay, titles, and more
* Custom inventory system where everything is an item: food, weapons, devices, etc
* All items can be dropped, given, used, picked up, or stored in certain places (other items, vehicles, etc)
* Ownable vehicles, houses, businesses, and more
* No "hard cap" to how many things you can own, but the more you own the more you pay in tax
* Stock your business with any items you want, and set custom prices
* Extra storage for businesses (floor items for sale, stockroom in back for hidden stuff)
* Security features like two-factor login, email alerts for login attempts, and more
* Animations and ped speech for extra RP goodness
* Players can make aliases for commands
* Choosable levels of GUI: Simple (input, list, message like SA-MP), Full (whole app layouts), or None (commands only)
* Custom keybinds. Server can set defaults, but players can bind/unbind keys for personalization
* *Everything* is dynamically changable in the server using commands and/or GUI
* Community-provided translations for GUI and server messages
* Automatic translator for chat (players can turn it on/off for themselves)
* Way too many other things to list here
## Setup
* Download the server from the [downloads page](https://gtaconnected.com/downloads) of the GTA Connected website.

View File

@@ -1,27 +1,27 @@
[
"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",
"Swedish"
[
"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",
"Swedish"
]

View File

@@ -1,145 +1,145 @@
[
{
"id": 0,
"englishName": "English",
"stringsFile": "english.json",
"isoCode": "en",
"flagImageFile": "uk.png",
"countries": ["gb", "us", "au", "bz", "ca", "ie", "jm", "nz", "za", "tt"],
"requiresUnicode": false,
"contributor": "Vortrex",
"enabled": true
},
{
"id": 1,
"englishName": "Russian",
"stringsFile": "russian.json",
"isoCode": "ru",
"flagImageFile": "ru.png",
"countries": ["ru", "ua"],
"requiresUnicode": false,
"contributor": "VNDTTS",
"enabled": true
},
{
"id": 2,
"englishName": "Polish",
"stringsFile": "polish.json",
"isoCode": "pl",
"flagImageFile": "pl.png",
"countries": ["pl"],
"requiresUnicode": false,
"contributor": "Suprise444",
"enabled": true
},
{
"id": 3,
"englishName": "Spanish",
"stringsFile": "spanish.json",
"isoCode": "es",
"flagImageFile": "es.png",
"countries": ["es", "ar", "bo", "cl", "co", "cr", "do", "ec", "sv", "gt", "hn", "mx", "ni", "pa", "py", "pe", "pr", "uy", "ve"],
"requiresUnicode": false,
"contributor": "PerikiyoXD",
"enabled": true
},
{
"id": 4,
"englishName": "Chinese",
"stringsFile": "chinese.json",
"isoCode": "zh",
"flagImageFile": "cn.png",
"countries": ["cn", "hk", "sg", "tw"],
"requiresUnicode": true,
"contributor": "Renzuko_Ctone",
"enabled": true
},
{
"id": 5,
"englishName": "Arabic",
"stringsFile": "arabic.json",
"isoCode": "ar",
"flagImageFile": "sa.png",
"countries": ["dz", "bh", "eg", "iq", "jo", "kw", "lb", "ly", "ma", "om", "qa", "sa", "sy", "tn", "ae", "ye"],
"requiresUnicode": true,
"contributor": "! KASIR",
"enabled": true
},
{
"id": 6,
"englishName": "Slovak",
"stringsFile": "slovak.json",
"isoCode": "sk",
"flagImageFile": "sk.png",
"countries": ["sk"],
"requiresUnicode": false,
"contributor": "UAKLAUS",
"enabled": false
},
{
"id": 7,
"englishName": "German",
"stringsFile": "german.json",
"isoCode": "de",
"flagImageFile": "de.png",
"countries": ["de", "at", "be", "ch", "li", "lu"],
"requiresUnicode": false,
"contributor": "Sladernimo",
"enabled": true
},
{
"id": 8,
"englishName": "French",
"stringsFile": "french.json",
"isoCode": "fr",
"flagImageFile": "fr.png",
"countries": ["fr", "cd", "bj", "bf", "cd", "cg", "ga", "gn", "ml", "mc", "ne", "sn"],
"requiresUnicode": false,
"contributor": "Cocam",
"enabled": false
},
{
"id": 9,
"englishName": "Japanese",
"stringsFile": "japanese.json",
"isoCode": "jp",
"flagImageFile": "jp.png",
"countries": ["jp"],
"requiresUnicode": true,
"contributor": "Cocam",
"enabled": false
},
{
"id": 10,
"englishName": "Finnish",
"stringsFile": "finnish.json",
"isoCode": "fi",
"flagImageFile": "fi.png",
"countries": ["fi"],
"requiresUnicode": false,
"contributor": "SIMBA_MEOW",
"enabled": true
},
{
"id": 11,
"englishName": "Lithuanian",
"stringsFile": "lithuanian.json",
"isoCode": "lt",
"flagImageFile": "lt.png",
"countries": ["lt"],
"requiresUnicode": false,
"contributor": "dovis",
"enabled": false
},
{
"id": 12,
"englishName": "Latvian",
"stringsFile": "latvian.json",
"isoCode": "lv",
"flagImageFile": "lv.png",
"countries": ["lv"],
"requiresUnicode": false,
"contributor": "YuOn",
"enabled": false
}
[
{
"id": 0,
"englishName": "English",
"stringsFile": "english.json",
"isoCode": "en",
"flagImageFile": "uk.png",
"countries": ["gb", "us", "au", "bz", "ca", "ie", "jm", "nz", "za", "tt"],
"requiresUnicode": false,
"contributor": "Vortrex",
"enabled": true
},
{
"id": 1,
"englishName": "Russian",
"stringsFile": "russian.json",
"isoCode": "ru",
"flagImageFile": "ru.png",
"countries": ["ru", "ua"],
"requiresUnicode": false,
"contributor": "VNDTTS",
"enabled": true
},
{
"id": 2,
"englishName": "Polish",
"stringsFile": "polish.json",
"isoCode": "pl",
"flagImageFile": "pl.png",
"countries": ["pl"],
"requiresUnicode": false,
"contributor": "Suprise444",
"enabled": true
},
{
"id": 3,
"englishName": "Spanish",
"stringsFile": "spanish.json",
"isoCode": "es",
"flagImageFile": "es.png",
"countries": ["es", "ar", "bo", "cl", "co", "cr", "do", "ec", "sv", "gt", "hn", "mx", "ni", "pa", "py", "pe", "pr", "uy", "ve"],
"requiresUnicode": false,
"contributor": "PerikiyoXD",
"enabled": true
},
{
"id": 4,
"englishName": "Chinese",
"stringsFile": "chinese.json",
"isoCode": "zh",
"flagImageFile": "cn.png",
"countries": ["cn", "hk", "sg", "tw"],
"requiresUnicode": true,
"contributor": "Renzuko_Ctone",
"enabled": true
},
{
"id": 5,
"englishName": "Arabic",
"stringsFile": "arabic.json",
"isoCode": "ar",
"flagImageFile": "sa.png",
"countries": ["dz", "bh", "eg", "iq", "jo", "kw", "lb", "ly", "ma", "om", "qa", "sa", "sy", "tn", "ae", "ye"],
"requiresUnicode": true,
"contributor": "! KASIR",
"enabled": true
},
{
"id": 6,
"englishName": "Slovak",
"stringsFile": "slovak.json",
"isoCode": "sk",
"flagImageFile": "sk.png",
"countries": ["sk"],
"requiresUnicode": false,
"contributor": "UAKLAUS",
"enabled": false
},
{
"id": 7,
"englishName": "German",
"stringsFile": "german.json",
"isoCode": "de",
"flagImageFile": "de.png",
"countries": ["de", "at", "be", "ch", "li", "lu"],
"requiresUnicode": false,
"contributor": "Sladernimo",
"enabled": true
},
{
"id": 8,
"englishName": "French",
"stringsFile": "french.json",
"isoCode": "fr",
"flagImageFile": "fr.png",
"countries": ["fr", "cd", "bj", "bf", "cd", "cg", "ga", "gn", "ml", "mc", "ne", "sn"],
"requiresUnicode": false,
"contributor": "Cocam",
"enabled": false
},
{
"id": 9,
"englishName": "Japanese",
"stringsFile": "japanese.json",
"isoCode": "jp",
"flagImageFile": "jp.png",
"countries": ["jp"],
"requiresUnicode": true,
"contributor": "Cocam",
"enabled": false
},
{
"id": 10,
"englishName": "Finnish",
"stringsFile": "finnish.json",
"isoCode": "fi",
"flagImageFile": "fi.png",
"countries": ["fi"],
"requiresUnicode": false,
"contributor": "SIMBA_MEOW",
"enabled": true
},
{
"id": 11,
"englishName": "Lithuanian",
"stringsFile": "lithuanian.json",
"isoCode": "lt",
"flagImageFile": "lt.png",
"countries": ["lt"],
"requiresUnicode": false,
"contributor": "dovis",
"enabled": false
},
{
"id": 12,
"englishName": "Latvian",
"stringsFile": "latvian.json",
"isoCode": "lv",
"flagImageFile": "lv.png",
"countries": ["lv"],
"requiresUnicode": false,
"contributor": "YuOn",
"enabled": false
}
]

View File

@@ -1,8 +1,8 @@
{
"host": "",
"user": "",
"pass": "",
"name": "",
"port": 3306,
"usePersistentConnection": false
{
"host": "",
"user": "",
"pass": "",
"name": "",
"port": 3306,
"usePersistentConnection": false
}

View File

@@ -1,15 +1,15 @@
{
"sendChat": false,
"sendEvents": false,
"sendConnectEvents": false,
"sendVehicleEvents": false,
"sendDeathEvents": false,
"sendAdmin": false,
"sendClan": false,
"sendAction": false,
"webhook": {
"enabled": false,
"webhookBaseURL": "",
"pass": ""
}
{
"sendChat": false,
"sendEvents": false,
"sendConnectEvents": false,
"sendVehicleEvents": false,
"sendDeathEvents": false,
"sendAdmin": false,
"sendClan": false,
"sendAction": false,
"webhook": {
"enabled": false,
"webhookBaseURL": "",
"pass": ""
}
}

View File

@@ -1,13 +0,0 @@
{
"passiveIncomePerPayDay": 2000,
"applyTax": true,
"applyUpkeep": true,
"grossIncomeMultiplier": 1.0,
"incomeTaxRate": 0.7,
"currencyString": "${AMOUNT}",
"upKeepCosts": {
"upKeepPerVehicle": 250,
"upKeepPerHouse": 350,
"upKeepPerBusiness": 600
}
}

View File

@@ -1,27 +1,27 @@
{
"enabled": false,
"method": "http",
"smtp": {
"host": "",
"port": 0,
"username": "",
"password": "",
"from": "",
"fromName": "",
"useTLS": true
},
"http": {
"password": "",
"baseURL": ""
},
"bodyContent": {
"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 login 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}",
"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}",
"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!"
}
{
"enabled": false,
"method": "http",
"smtp": {
"host": "",
"port": 0,
"username": "",
"password": "",
"from": "",
"fromName": "",
"useTLS": true
},
"http": {
"password": "",
"baseURL": ""
},
"bodyContent": {
"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 login 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}",
"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}",
"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!"
}
}

View File

@@ -1,109 +1,114 @@
{
"config": {
"shortHoldDuration": 500,
"longHoldDuration": 1500,
"coolDownBetweenUse": 500
},
"defaultKeyBinds": [
{
"keyName": "k",
"commandString": "engine",
"keyState": 1
},
{
"keyName": "l",
"commandString": "lights",
"keyState": 1
},
{
"keyName": "j",
"commandString": "lock",
"keyState": 1
},
{
"keyName": "f",
"commandString": "enter",
"keyState": 1
},
{
"keyName": "g",
"commandString": "passenger",
"keyState": 1
},
{
"keyName": "m",
"commandString": "cursor",
"keyState": 1
},
{
"keyName": "o",
"commandString": "drop",
"keyState": 1
},
{
"keyName": "p",
"commandString": "pickup",
"keyState": 1
},
{
"keyName": "u",
"commandString": "use",
"keyState": 1
},
{
"keyName": "i",
"commandString": "inv",
"keyState": 1
},
{
"keyName": "0",
"commandString": "item 0",
"keyState": 1
},
{
"keyName": "1",
"commandString": "item 1",
"keyState": 1
},
{
"keyName": "2",
"commandString": "item 2",
"keyState": 1
},
{
"keyName": "3",
"commandString": "item 3",
"keyState": 1
},
{
"keyName": "4",
"commandString": "item 4",
"keyState": 1
},
{
"keyName": "5",
"commandString": "item 5",
"keyState": 1
},
{
"keyName": "6",
"commandString": "item 6",
"keyState": 1
},
{
"keyName": "7",
"commandString": "item 7",
"keyState": 1
},
{
"keyName": "8",
"commandString": "item 8",
"keyState": 1
},
{
"keyName": "9",
"commandString": "item 9",
"keyState": 1
}
]
{
"config": {
"shortHoldDuration": 500,
"longHoldDuration": 1500,
"coolDownBetweenUse": 500
},
"defaultKeyBinds": [
{
"keyName": "k",
"commandString": "engine",
"keyState": 1
},
{
"keyName": "l",
"commandString": "lights",
"keyState": 1
},
{
"keyName": "j",
"commandString": "lock",
"keyState": 1
},
{
"keyName": "f",
"commandString": "enter",
"keyState": 1
},
{
"keyName": "g",
"commandString": "passenger",
"keyState": 1
},
{
"keyName": "m",
"commandString": "cursor",
"keyState": 1
},
{
"keyName": "o",
"commandString": "drop",
"keyState": 1
},
{
"keyName": "p",
"commandString": "pickup",
"keyState": 1
},
{
"keyName": "u",
"commandString": "use",
"keyState": 1
},
{
"keyName": "i",
"commandString": "inv",
"keyState": 1
},
{
"keyName": "0",
"commandString": "item 0",
"keyState": 1
},
{
"keyName": "1",
"commandString": "item 1",
"keyState": 1
},
{
"keyName": "2",
"commandString": "item 2",
"keyState": 1
},
{
"keyName": "3",
"commandString": "item 3",
"keyState": 1
},
{
"keyName": "4",
"commandString": "item 4",
"keyState": 1
},
{
"keyName": "5",
"commandString": "item 5",
"keyState": 1
},
{
"keyName": "6",
"commandString": "item 6",
"keyState": 1
},
{
"keyName": "7",
"commandString": "item 7",
"keyState": 1
},
{
"keyName": "8",
"commandString": "item 8",
"keyState": 1
},
{
"keyName": "9",
"commandString": "item 9",
"keyState": 1
},
{
"keyName": "f5",
"commandString": "scoreboard",
"keyState": 1
}
]
}

View File

@@ -1,150 +1,150 @@
{
"apiEmail": "example@example.com",
"defaultLanguageId": 0,
"translateURL": "http://api.mymemory.translated.net/get?de={3}&q={0}&langpair={1}|{2}",
"locales": [
{
"id": 0,
"englishName": "English",
"stringsFile": "english.json",
"isoCode": "en",
"flagImageFile": "uk.png",
"countries": ["gb", "us", "au", "bz", "ca", "ie", "jm", "nz", "za", "tt"],
"requiresUnicode": false,
"contributor": "Vortrex",
"enabled": true
},
{
"id": 1,
"englishName": "Russian",
"stringsFile": "russian.json",
"isoCode": "ru",
"flagImageFile": "ru.png",
"countries": ["ru", "ua"],
"requiresUnicode": false,
"contributor": "VNDTTS",
"enabled": true
},
{
"id": 2,
"englishName": "Polish",
"stringsFile": "polish.json",
"isoCode": "pl",
"flagImageFile": "pl.png",
"countries": ["pl"],
"requiresUnicode": false,
"contributor": "Suprise444",
"enabled": true
},
{
"id": 3,
"englishName": "Spanish",
"stringsFile": "spanish.json",
"isoCode": "es",
"flagImageFile": "es.png",
"countries": ["es", "ar", "bo", "cl", "co", "cr", "do", "ec", "sv", "gt", "hn", "mx", "ni", "pa", "py", "pe", "pr", "uy", "ve"],
"requiresUnicode": false,
"contributor": "PerikiyoXD",
"enabled": true
},
{
"id": 4,
"englishName": "Chinese",
"stringsFile": "chinese.json",
"isoCode": "zh",
"flagImageFile": "cn.png",
"countries": ["cn", "hk", "sg", "tw"],
"requiresUnicode": true,
"contributor": "Renzuko_Ctone",
"enabled": true
},
{
"id": 5,
"englishName": "Arabic",
"stringsFile": "arabic.json",
"isoCode": "ar",
"flagImageFile": "sa.png",
"countries": ["dz", "bh", "eg", "iq", "jo", "kw", "lb", "ly", "ma", "om", "qa", "sa", "sy", "tn", "ae", "ye"],
"requiresUnicode": true,
"contributor": "! KASIR",
"enabled": true
},
{
"id": 6,
"englishName": "Slovak",
"stringsFile": "slovak.json",
"isoCode": "sk",
"flagImageFile": "sk.png",
"countries": ["sk"],
"requiresUnicode": false,
"contributor": "UAKLAUS",
"enabled": false
},
{
"id": 7,
"englishName": "German",
"stringsFile": "german.json",
"isoCode": "de",
"flagImageFile": "de.png",
"countries": ["de", "at", "be", "ch", "li", "lu"],
"requiresUnicode": false,
"contributor": "Sladernimo",
"enabled": true
},
{
"id": 8,
"englishName": "French",
"stringsFile": "french.json",
"isoCode": "fr",
"flagImageFile": "fr.png",
"countries": ["fr", "cd", "bj", "bf", "cd", "cg", "ga", "gn", "ml", "mc", "ne", "sn"],
"requiresUnicode": false,
"contributor": "Cocam",
"enabled": false
},
{
"id": 9,
"englishName": "Japanese",
"stringsFile": "japanese.json",
"isoCode": "jp",
"flagImageFile": "jp.png",
"countries": ["jp"],
"requiresUnicode": true,
"contributor": "Cocam",
"enabled": false
},
{
"id": 10,
"englishName": "Finnish",
"stringsFile": "finnish.json",
"isoCode": "fi",
"flagImageFile": "fi.png",
"countries": ["fi"],
"requiresUnicode": false,
"contributor": "SIMBA_MEOW",
"enabled": true
},
{
"id": 11,
"englishName": "Lithuanian",
"stringsFile": "lithuanian.json",
"isoCode": "lt",
"flagImageFile": "lt.png",
"countries": ["lt"],
"requiresUnicode": false,
"contributor": "dovis",
"enabled": false
},
{
"id": 12,
"englishName": "Latvian",
"stringsFile": "latvian.json",
"isoCode": "lv",
"flagImageFile": "lv.png",
"countries": ["lv"],
"requiresUnicode": false,
"contributor": "YuOn",
"enabled": false
}
]
{
"apiEmail": "example@example.com",
"defaultLanguageId": 0,
"translateURL": "http://api.mymemory.translated.net/get?de={3}&q={0}&langpair={1}|{2}",
"locales": [
{
"id": 0,
"englishName": "English",
"stringsFile": "english.json",
"isoCode": "en",
"flagImageFile": "uk.png",
"countries": ["gb", "us", "au", "bz", "ca", "ie", "jm", "nz", "za", "tt"],
"requiresUnicode": false,
"contributor": "Vortrex",
"enabled": true
},
{
"id": 1,
"englishName": "Russian",
"stringsFile": "russian.json",
"isoCode": "ru",
"flagImageFile": "ru.png",
"countries": ["ru", "ua"],
"requiresUnicode": false,
"contributor": "VNDTTS",
"enabled": true
},
{
"id": 2,
"englishName": "Polish",
"stringsFile": "polish.json",
"isoCode": "pl",
"flagImageFile": "pl.png",
"countries": ["pl"],
"requiresUnicode": false,
"contributor": "Suprise444",
"enabled": true
},
{
"id": 3,
"englishName": "Spanish",
"stringsFile": "spanish.json",
"isoCode": "es",
"flagImageFile": "es.png",
"countries": ["es", "ar", "bo", "cl", "co", "cr", "do", "ec", "sv", "gt", "hn", "mx", "ni", "pa", "py", "pe", "pr", "uy", "ve"],
"requiresUnicode": false,
"contributor": "PerikiyoXD",
"enabled": true
},
{
"id": 4,
"englishName": "Chinese",
"stringsFile": "chinese.json",
"isoCode": "zh",
"flagImageFile": "cn.png",
"countries": ["cn", "hk", "sg", "tw"],
"requiresUnicode": true,
"contributor": "Renzuko_Ctone",
"enabled": true
},
{
"id": 5,
"englishName": "Arabic",
"stringsFile": "arabic.json",
"isoCode": "ar",
"flagImageFile": "sa.png",
"countries": ["dz", "bh", "eg", "iq", "jo", "kw", "lb", "ly", "ma", "om", "qa", "sa", "sy", "tn", "ae", "ye"],
"requiresUnicode": true,
"contributor": "! KASIR",
"enabled": true
},
{
"id": 6,
"englishName": "Slovak",
"stringsFile": "slovak.json",
"isoCode": "sk",
"flagImageFile": "sk.png",
"countries": ["sk"],
"requiresUnicode": false,
"contributor": "UAKLAUS",
"enabled": false
},
{
"id": 7,
"englishName": "German",
"stringsFile": "german.json",
"isoCode": "de",
"flagImageFile": "de.png",
"countries": ["de", "at", "be", "ch", "li", "lu"],
"requiresUnicode": false,
"contributor": "Sladernimo",
"enabled": true
},
{
"id": 8,
"englishName": "French",
"stringsFile": "french.json",
"isoCode": "fr",
"flagImageFile": "fr.png",
"countries": ["fr", "cd", "bj", "bf", "cd", "cg", "ga", "gn", "ml", "mc", "ne", "sn"],
"requiresUnicode": false,
"contributor": "Cocam",
"enabled": false
},
{
"id": 9,
"englishName": "Japanese",
"stringsFile": "japanese.json",
"isoCode": "jp",
"flagImageFile": "jp.png",
"countries": ["jp"],
"requiresUnicode": true,
"contributor": "Cocam",
"enabled": false
},
{
"id": 10,
"englishName": "Finnish",
"stringsFile": "finnish.json",
"isoCode": "fi",
"flagImageFile": "fi.png",
"countries": ["fi"],
"requiresUnicode": false,
"contributor": "SIMBA_MEOW",
"enabled": true
},
{
"id": 11,
"englishName": "Lithuanian",
"stringsFile": "lithuanian.json",
"isoCode": "lt",
"flagImageFile": "lt.png",
"countries": ["lt"],
"requiresUnicode": false,
"contributor": "dovis",
"enabled": false
},
{
"id": 12,
"englishName": "Latvian",
"stringsFile": "latvian.json",
"isoCode": "lv",
"flagImageFile": "lv.png",
"countries": ["lv"],
"requiresUnicode": false,
"contributor": "YuOn",
"enabled": false
}
]
}

8
config/security.json Normal file
View File

@@ -0,0 +1,8 @@
{
"accountSaltHash": [
"LGj6w8SRwJEJ95XH"
],
"accountPasswordSaltAlgorithm": [
"v.roleplay.{SALTHASH}.{NAME}.{PASSWORD}"
]
}

View File

@@ -66,6 +66,22 @@ CREATE TABLE IF NOT EXISTS `acct_contact` (
-- Dumping data for table v-roleplay.acct_contact: ~0 rows (approximately)
-- Dumping structure for table v-roleplay.acct_cmd
CREATE TABLE `acct_cmd` (
`acct_cmd_id` int(11) NOT NULL,
`acct_cmd_acct` int(11) NOT NULL DEFAULT '1',
`acct_cmd_for_cmd` varchar(128) NOT NULL DEFAULT '',
`acct_cmd_alias_cmd` varchar(128) NOT NULL DEFAULT '',
`acct_cmd_deleted` tinyint(1) NOT NULL DEFAULT '0',
`acct_cmd_enabled` tinyint(1) NOT NULL DEFAULT '0',
`acct_cmd_when_added` bigint(32) NOT NULL DEFAULT '0'
PRIMARY KEY (`acct_cmd_id`),
KEY `acct_cmd_acct` (`acct_cmd_acct`),
CONSTRAINT `fk_acct_cmd_acct` FOREIGN KEY (`acct_cmd_acct`) REFERENCES `acct_main` (`acct_id`) ON DELETE CASCADE ON UPDATE CASCADE,
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='Account - Command Aliases';
-- Dumping data for table v-roleplay.acct_cmd: ~0 rows (approximately)
-- Dumping structure for table v-roleplay.acct_hotkey
CREATE TABLE IF NOT EXISTS `acct_hotkey` (
`acct_hotkey_id` int(11) NOT NULL AUTO_INCREMENT,

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

41
info/ECONOMY.md Normal file
View File

@@ -0,0 +1,41 @@
# Economy Information
### Basic Information
Each server has it's own independent economy with simulated inflation and is designed to slowly self-repair over time, assuming nothing is affecting it too heavily.
---
### Asset Ownership
Any player or clan is allowed to own as many businesses, vehicles, and houses as they want. However, it should be noted that the more you own, the more upkeep (via taxes, insurance, etc) is required. Failure to maintain this upkeep for too long will automatically force you to lose the unmaintained assets. Vehicle owners can park their car anywhere (subject to IC parking laws), store items in the trunk or dash compartment, give anybody access, and set the price if they want to make it available to buy, and more. Business owners can stock their store with any item they want, set what prices they want for any item for sale, close/open the business, keep a stock of items in the business's storage, force people to pay a fee to enter, and more. House owners can store items in their house, purchase a safe, decorate with furniture, give anybody access, and more.
---
### Ordering Items for a Business
Ordering items is simple: just use the /bizorder command.
You'll need to specify which item you want to order and how many.
Remember, the prices will vary depending on certain circumstances.
The formula is as follows:
> Base price * server inflation * demand * risk * amount
**Here's a breakdown on how the above formula works:**
* First, each item has a base price. This value will never change.
* Next, the base price is multiplied by the server's current inflation value. When the servers were first opened, the inflation value is 100%, which means no inflation. Everything cost 100% of it's calculated price. However, the inflation will slowly increase over time, simulating realistic economy inflation.
* Next, the inflated price is then multiplied by the demand factor, which is determined by how much demand there is for the item you want. Every 10 of the item ordered increases the demand value by 10%, and this will slowly go back down over time. If another business just ordered 100 of the item you want, the demand has forced the item's order price to increase by 100%, which means it's now double the original price. This simulates the things involved with increased demand, such as the extra manufacturing and shipping needed to get this item imported to your business.
* Next, the cost is multiplied by a risk value. This value never changes, and varies depending on the item. For illegal items, the risk value will be lower for less-risky items and higher as they get worse. For example, a shotgun versus an AK-47 have different risk levels, as an AK-47 is a far deadlier and a harder to get weapon, and is more difficult to conceal through customs. This simulates the "risk" of ordering items like these. For legal items, there is no risk so the risk price won't increase for those.
* Finally, the order cost is multiplied by the amount you want to order.
**An example of this formula in action is below ... shown for an order for 10 AK-47's with no inflation**
*The demand is increased by 10% since you're ordering 10 of them. 1 = 100% of the normal cost, 1.1 = 110%, and so on.*
> Base price $1000
> x inflation 1 = $1000
> x demand 1.1 = $1100
> x risk 5 = $5500
> x amount 10 = $55000
So as you can see, the total cost to order 10 AK-47's in this scenario is $55,000. Remember, an AK-47 is a deadly and uncommon weapon (and highly illegal!) so it's a very risky and costly thing to do business with.

View File

@@ -17,12 +17,9 @@
"AnimationStopCommandTip": "استخدم {1} لإيقاف الرسوم المتحركة",
"CantBanClient": "لا يمكنك حظر هذا الإعب",
"PlayerAccountBanned": "تم حظر حساب {1}",
"ClanNotFound": "لم يتم العثور على المجموعة",
"ClanNameTaken": "توجد مجموعة بهذا الاسم بالفعل",
"PlayerNotFound": "الاعب غير موجود",
"ClanCantRemoveRanks": "لا يمكنك إزالة رتب المجموعة",
"ClanCantAddRanks": "لأ يمكنك إضافة رتب",
"ClanRankNotFound": "رتبة غير موجودهـ",
"ClanCantChangeMemberTag": "ليس لديك الصلاحيات لتعديل على علامات رتب الاعضاء",
"ClanPlayerNotInSameClan": "الاعب غير موجود بمجموعتك",
"ClanCantChangeRankLevel": "ليس لديك صلاحيات لتغيير مستوى رتبة المجموعة",
@@ -655,28 +652,6 @@
"LeftWrist": "معصم اليد اليسرى",
"RightWrist": "معصم اليد اليمنى"
},
"ActionTips": {
"VehicleEngineOffWhenEnteringKey": "استخدم {1} لتشغيل أو إيقاف تشغيل محرك السيارة",
"VehicleLockedAfterEntryAttempt": "استخدم {1} لقفل أو إلغاء تأمين مركبة",
"ShowItemsAfterPurchase": "استخدم {1} لمشاهدة مخزونك",
"BuyCommandAfterEnterBusiness": "استخدم {1} لشراء عناصر من شركة",
"UseItemKeyAfterEquipping": "استخدم {1} لاستخدام العنصر المجهز الخاص بك",
"UseItemKeyAfterEquippingWalkieTalkie": "استخدم {1} لتشغيل الراديو أو إيقاف تشغيله",
"RadioCommandAfterEnablingWalkieTalkie": "استخدم {1} للتحدث في الراديو الخاص بك",
"ReplyToDirectMessage": "استخدم {1} للرد بسهولة على رسالة خاصة",
"UseItemKeyAmmoAfterEquippingWeapon": "استخدم {1} لتحميل ذخيرة في سلاحك المجهز",
"AnimationStop": "استخدم {1} لإيقاف الرسم المتحرك",
"JobEquipmentInventory": "معدات العمل موجودة في مخزونك. استخدم {1} لمشاهدتها.",
"ViewInventory": "استخدم {1} لمشاهدة عناصرك",
"VehicleRepairItemUsage": "قف بجانب سيارة واستخدم {1} لإصلاحها",
"VehicleColourItemUsage": "قف بجوار سيارة واستخدم {1} لتغيير لونها",
"VehiclePartItemUsage": "قف بجوار سيارة واستخدم {1} للترقية باستخدام {2}",
"AmmoClipItemUsage": "جهز السلاح واستخدم {1} لتحميل الذخيرة فيه",
"GenericItemUsage": "استخدم {1} لاستخدام {2}",
"EnterJobVehicleForRoute": "أدخل سيارة عمل قريبة لبدء مسار عمل",
"JobLocations": "قم بزيارة موقع العمل للحصول على وظيفة. استخدم {1} للعثور على موقع عمل",
"JobRouteStart": "استخدم {1} لبدء مسار عمل بهذه السيارة"
},
"DisconnectReasons": {
"Unknown": "غير معروف",
"LostConnection": "انقطع الإتصال",
@@ -752,5 +727,60 @@
"Cancel": "Cancel",
"AlreadyOwnVehicle": "You already own this vehicle!",
"PropertyEntranceFeeLabel": "Entrance Fee: {1}",
"NeedToBeInJobVehicle": "You need to be in a job vehicle!"
}
"NeedToBeInJobVehicle": "You need to be in a job vehicle!",
"InvalidJobRank": "Job rank not found!",
"PayPhoneRecipientAnswered": "Somebody answered the call. Use normal chat to talk to them.",
"PayPhoneAnswered": "You answered the phone. Use normal chat to talk to the caller.",
"PayPhoneRecipientHangup": "The line was disconnected. You have been charged {1}",
"PayPhoneHangup": "You hung up the phone.",
"AlreadyUsingPayPhone": "You are already using a payphone!",
"NotUsingPayPhone": "You are not using a payphone!",
"NoPayPhoneCloseEnough": "There is no payphone close enough!",
"PayPhoneNotRinging": "This payphone is not ringing!",
"PayPhoneOccupied": "This payphone is already being used by someone else!",
"PayPhoneOccupantSwitched": "A different voice is now on the line",
"PayPhoneGiven": "You gave the phone to {1}",
"PayPhoneReceived": "{1} gave you the phone",
"PayPhoneUnableToCallPlayer": "You can't call {1} at this time. Please try again later.",
"ActionTips": {
"VehicleEngineOffWhenEnteringKey": "استخدم {1} لتشغيل أو إيقاف تشغيل محرك السيارة",
"VehicleLockedAfterEntryAttempt": "استخدم {1} لقفل أو إلغاء تأمين مركبة",
"ShowItemsAfterPurchase": "استخدم {1} لمشاهدة مخزونك",
"BuyCommandAfterEnterBusiness": "استخدم {1} لشراء عناصر من شركة",
"UseItemKeyAfterEquipping": "استخدم {1} لاستخدام العنصر المجهز الخاص بك",
"UseItemKeyAfterEquippingWalkieTalkie": "استخدم {1} لتشغيل الراديو أو إيقاف تشغيله",
"RadioCommandAfterEnablingWalkieTalkie": "استخدم {1} للتحدث في الراديو الخاص بك",
"ReplyToDirectMessage": "استخدم {1} للرد بسهولة على رسالة خاصة",
"UseItemKeyAmmoAfterEquippingWeapon": "استخدم {1} لتحميل ذخيرة في سلاحك المجهز",
"AnimationStop": "استخدم {1} لإيقاف الرسم المتحرك",
"JobEquipmentInventory": "معدات العمل موجودة في مخزونك. استخدم {1} لمشاهدتها.",
"ViewInventory": "استخدم {1} لمشاهدة عناصرك",
"VehicleRepairItemUsage": "قف بجانب سيارة واستخدم {1} لإصلاحها",
"VehicleColourItemUsage": "قف بجوار سيارة واستخدم {1} لتغيير لونها",
"VehiclePartItemUsage": "قف بجوار سيارة واستخدم {1} للترقية باستخدام {2}",
"AmmoClipItemUsage": "جهز السلاح واستخدم {1} لتحميل الذخيرة فيه",
"GenericItemUsage": "استخدم {1} لاستخدام {2}",
"EnterJobVehicleForRoute": "أدخل سيارة عمل قريبة لبدء مسار عمل",
"JobLocations": "قم بزيارة موقع العمل للحصول على وظيفة. استخدم {1} للعثور على موقع عمل",
"JobRouteStart": "استخدم {1} لبدء مسار عمل بهذه السيارة",
"PayPhoneFirstUse": "Use {1} to end the call, and {2} to give the phone to somebody nearby"
},
"NoBusinessesWithinRange": "There are no businesses within {1} meters",
"NoHousesWithinRange": "There are no houses within {1} meters",
"NoPayPhonesWithinRange": "There are no payphones within {1} meters",
"HeaderBusinessesInRangeList": "Businesses (within {1} meters)",
"HeaderHousesInRangeList": "Businesses (within {1} meters)",
"HeaderPayPhonesInRangeList": "Businesses (within {1} meters)",
"HeaderCommandsForStaffFlagList": "Admin Commands ({1})",
"PlayerLocateDistanceAndDirection": "{1} is {2} meters {3}",
"MustBeNumber": "You need to use a number!",
"HeaderJobRoutesList": "Job Routes ({1})",
"HeaderJobRouteInfo": "Job Route Information (${1})",
"InvalidJobRoute": "Job route not found!",
"PayPhoneDeleted": "The payphone was deleted",
"PayPhoneAnswer": "Use {1} to answer the payphone",
"ResetActionTipsConfirm": "Are you sure you want to reset all seen action tips?",
"ActionTipsReset": "All seen action tips have been reset.",
"NormalChatDisabled": "Normal chat is disabled by server admin. Use chat commands instead.",
"GlobalChatDisabled": "Global out-of-character chat is disabled by server admin"
}

View File

@@ -16,12 +16,9 @@
"InvalidAnimationDistance": "The distance must be between 0 and 3",
"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",
@@ -653,28 +650,6 @@
"LeftWrist": "Left Wrist",
"RightWrist": "Right Wrist"
},
"ActionTips": {
"VehicleEngineOffWhenEnteringKey": "Use {1} to turn on or off a vehicle's engine",
"VehicleLockedAfterEntryAttempt": "Use {1} to lock or unlock a vehicle",
"ShowItemsAfterPurchase": "Use {1} to see your inventory",
"BuyCommandAfterEnterBusiness": "Use {1} to buy items from a business",
"UseItemKeyAfterEquipping": "Use {1} to use your equipped item",
"UseItemKeyAfterEquippingWalkieTalkie": "Use {1} to turn on or off your radio",
"RadioCommandAfterEnablingWalkieTalkie": "Use {1} to talk on your radio",
"ReplyToDirectMessage": "Use {1} to easily reply to a private message",
"UseItemKeyAmmoAfterEquippingWeapon": "Use {1} to load an ammo item into your equipped weapon",
"AnimationStop": "Use {1} to stop your animation",
"JobEquipmentInventory": "The job equipment is in your inventory. Use {1} to see them.",
"ViewInventory": "Use {1} to see your items",
"VehicleRepairItemUsage": "Stand next to a vehicle and use {1} to repair it",
"VehicleColourItemUsage": "Stand next to a vehicle and use {1} to change it's colour",
"VehiclePartItemUsage": "Stand next to a vehicle and use {1} to upgrade with {2}",
"AmmoClipItemUsage": "Equip the weapon and use {1} to load ammo into it",
"GenericItemUsage": "Use {1} to use the {2}",
"EnterJobVehicleForRoute": "Enter a job vehicle nearby to start a job route",
"JobLocations": "Visit a job location to get a job. Use {1} to find a job location",
"JobRouteStart": "Use {1} to start a job route with this vehicle"
},
"DisconnectReasons": {
"Unknown": "Unknown",
"LostConnection": "Lost Connection",
@@ -750,5 +725,60 @@
"Cancel": "Cancel",
"AlreadyOwnVehicle": "You already own this vehicle!",
"PropertyEntranceFeeLabel": "Entrance Fee: {1}",
"NeedToBeInJobVehicle": "You need to be in a job vehicle!"
}
"NeedToBeInJobVehicle": "You need to be in a job vehicle!",
"InvalidJobRank": "Job rank not found!",
"PayPhoneRecipientAnswered": "Somebody answered the call. Use normal chat to talk to them.",
"PayPhoneAnswered": "You answered the phone. Use normal chat to talk to the caller.",
"PayPhoneRecipientHangup": "The line was disconnected. You have been charged {1}",
"PayPhoneHangup": "You hung up the phone.",
"AlreadyUsingPayPhone": "You are already using a payphone!",
"NotUsingPayPhone": "You are not using a payphone!",
"NoPayPhoneCloseEnough": "There is no payphone close enough!",
"PayPhoneNotRinging": "This payphone is not ringing!",
"PayPhoneOccupied": "This payphone is already being used by someone else!",
"PayPhoneOccupantSwitched": "A different voice is now on the line",
"PayPhoneGiven": "You gave the phone to {1}",
"PayPhoneReceived": "{1} gave you the phone",
"PayPhoneUnableToCallPlayer": "You can't call {1} at this time. Please try again later.",
"ActionTips": {
"VehicleEngineOffWhenEnteringKey": "Use {1} to turn on or off a vehicle's engine",
"VehicleLockedAfterEntryAttempt": "Use {1} to lock or unlock a vehicle",
"ShowItemsAfterPurchase": "Use {1} to see your inventory",
"BuyCommandAfterEnterBusiness": "Use {1} to buy items from a business",
"UseItemKeyAfterEquipping": "Use {1} to use your equipped item",
"UseItemKeyAfterEquippingWalkieTalkie": "Use {1} to turn on or off your radio",
"RadioCommandAfterEnablingWalkieTalkie": "Use {1} to talk on your radio",
"ReplyToDirectMessage": "Use {1} to easily reply to a private message",
"UseItemKeyAmmoAfterEquippingWeapon": "Use {1} to load an ammo item into your equipped weapon",
"AnimationStop": "Use {1} to stop your animation",
"JobEquipmentInventory": "The job equipment is in your inventory. Use {1} to see them.",
"ViewInventory": "Use {1} to see your items",
"VehicleRepairItemUsage": "Stand next to a vehicle and use {1} to repair it",
"VehicleColourItemUsage": "Stand next to a vehicle and use {1} to change it's colour",
"VehiclePartItemUsage": "Stand next to a vehicle and use {1} to upgrade with {2}",
"AmmoClipItemUsage": "Equip the weapon and use {1} to load ammo into it",
"GenericItemUsage": "Use {1} to use the {2}",
"EnterJobVehicleForRoute": "Enter a job vehicle nearby to start a job route",
"JobLocations": "Visit a job location to get a job. Use {1} to find a job location",
"JobRouteStart": "Use {1} to start a job route with this vehicle",
"PayPhoneFirstUse": "Use {1} to end the call, and {2} to give the phone to somebody nearby"
},
"NoBusinessesWithinRange": "There are no businesses within {1} meters",
"NoHousesWithinRange": "There are no houses within {1} meters",
"NoPayPhonesWithinRange": "There are no payphones within {1} meters",
"HeaderBusinessesInRangeList": "Businesses (within {1} meters)",
"HeaderHousesInRangeList": "Businesses (within {1} meters)",
"HeaderPayPhonesInRangeList": "Businesses (within {1} meters)",
"HeaderCommandsForStaffFlagList": "Admin Commands ({1})",
"PlayerLocateDistanceAndDirection": "{1} is {2} meters {3}",
"MustBeNumber": "You need to use a number!",
"HeaderJobRoutesList": "Job Routes ({1})",
"HeaderJobRouteInfo": "Job Route Information (${1})",
"InvalidJobRoute": "Job route not found!",
"PayPhoneDeleted": "The payphone was deleted",
"PayPhoneAnswer": "Use {1} to answer the payphone",
"ResetActionTipsConfirm": "Are you sure you want to reset all seen action tips?",
"ActionTipsReset": "All seen action tips have been reset.",
"NormalChatDisabled": "Normal chat is disabled by server admin. Use chat commands instead.",
"GlobalChatDisabled": "Global out-of-character chat is disabled by server admin"
}

View File

@@ -16,12 +16,9 @@
"AnimationStopCommandTip": "使用 {1} 以停止当前动作",
"CantBanClient": "你无法封禁该玩家",
"PlayerAccountBanned": "{1} 的账户已被封禁",
"ClanNotFound": "帮派不存在",
"ClanNameTaken": "该帮派名称已被占用",
"PlayerNotFound": "玩家不存在",
"ClanCantRemoveRanks": "无法清除帮派等级",
"ClanCantAddRanks": "无法增加帮派等级",
"ClanRankNotFound": "帮派等级不存在",
"ClanCantChangeMemberTag": "你无法更改帮派成员的标签",
"ClanPlayerNotInSameClan": "该玩家并不属于你的帮派",
"ClanCantChangeRankLevel": "你无法更改帮派等级",
@@ -651,28 +648,6 @@
"LeftWrist": "Left Wrist",
"RightWrist": "Right Wrist"
},
"ActionTips": {
"VehicleEngineOffWhenEnteringKey": "Use {1} to turn on or off a vehicle's engine",
"VehicleLockedAfterEntryAttempt": "Use {1} to lock or unlock a vehicle",
"ShowItemsAfterPurchase": "Use {1} to see your inventory",
"BuyCommandAfterEnterBusiness": "Use {1} to buy items from a business",
"UseItemKeyAfterEquipping": "Use {1} to use your equipped item",
"UseItemKeyAfterEquippingWalkieTalkie": "Use {1} to turn on or off your radio",
"RadioCommandAfterEnablingWalkieTalkie": "Use {1} to talk on your radio",
"ReplyToDirectMessage": "Use {1} to easily reply to a private message",
"UseItemKeyAmmoAfterEquippingWeapon": "Use {1} to load an ammo item into your equipped weapon",
"AnimationStop": "Use {1} to stop your animation",
"JobEquipmentInventory": "The job equipment is in your inventory. Use {1} to see them.",
"ViewInventory": "Use {1} to see your items",
"VehicleRepairItemUsage": "Stand next to a vehicle and use {1} to repair it",
"VehicleColourItemUsage": "Stand next to a vehicle and use {1} to change it's colour",
"VehiclePartItemUsage": "Stand next to a vehicle and use {1} to upgrade with {2}",
"AmmoClipItemUsage": "Equip the weapon and use {1} to load ammo into it",
"GenericItemUsage": "Use {1} to use the {2}",
"EnterJobVehicleForRoute": "Enter a job vehicle nearby to start a job route",
"JobLocations": "Visit a job location to get a job. Use {1} to find a job location",
"JobRouteStart": "Use {1} to start a job route with this vehicle"
},
"DisconnectReasons": {
"Unknown": "Unknown",
"LostConnection": "Lost Connection",
@@ -748,5 +723,60 @@
"Cancel": "Cancel",
"AlreadyOwnVehicle": "You already own this vehicle!",
"PropertyEntranceFeeLabel": "Entrance Fee: {1}",
"NeedToBeInJobVehicle": "You need to be in a job vehicle!"
"NeedToBeInJobVehicle": "You need to be in a job vehicle!",
"InvalidJobRank": "Job rank not found!",
"PayPhoneRecipientAnswered": "Somebody answered the call. Use normal chat to talk to them.",
"PayPhoneAnswered": "You answered the phone. Use normal chat to talk to the caller.",
"PayPhoneRecipientHangup": "The line was disconnected. You have been charged {1}",
"PayPhoneHangup": "You hung up the phone.",
"AlreadyUsingPayPhone": "You are already using a payphone!",
"NotUsingPayPhone": "You are not using a payphone!",
"NoPayPhoneCloseEnough": "There is no payphone close enough!",
"PayPhoneNotRinging": "This payphone is not ringing!",
"PayPhoneOccupied": "This payphone is already being used by someone else!",
"PayPhoneOccupantSwitched": "A different voice is now on the line",
"PayPhoneGiven": "You gave the phone to {1}",
"PayPhoneReceived": "{1} gave you the phone",
"PayPhoneUnableToCallPlayer": "You can't call {1} at this time. Please try again later.",
"ActionTips": {
"VehicleEngineOffWhenEnteringKey": "Use {1} to turn on or off a vehicle's engine",
"VehicleLockedAfterEntryAttempt": "Use {1} to lock or unlock a vehicle",
"ShowItemsAfterPurchase": "Use {1} to see your inventory",
"BuyCommandAfterEnterBusiness": "Use {1} to buy items from a business",
"UseItemKeyAfterEquipping": "Use {1} to use your equipped item",
"UseItemKeyAfterEquippingWalkieTalkie": "Use {1} to turn on or off your radio",
"RadioCommandAfterEnablingWalkieTalkie": "Use {1} to talk on your radio",
"ReplyToDirectMessage": "Use {1} to easily reply to a private message",
"UseItemKeyAmmoAfterEquippingWeapon": "Use {1} to load an ammo item into your equipped weapon",
"AnimationStop": "Use {1} to stop your animation",
"JobEquipmentInventory": "The job equipment is in your inventory. Use {1} to see them.",
"ViewInventory": "Use {1} to see your items",
"VehicleRepairItemUsage": "Stand next to a vehicle and use {1} to repair it",
"VehicleColourItemUsage": "Stand next to a vehicle and use {1} to change it's colour",
"VehiclePartItemUsage": "Stand next to a vehicle and use {1} to upgrade with {2}",
"AmmoClipItemUsage": "Equip the weapon and use {1} to load ammo into it",
"GenericItemUsage": "Use {1} to use the {2}",
"EnterJobVehicleForRoute": "Enter a job vehicle nearby to start a job route",
"JobLocations": "Visit a job location to get a job. Use {1} to find a job location",
"JobRouteStart": "Use {1} to start a job route with this vehicle",
"PayPhoneFirstUse": "Use {1} to end the call, and {2} to give the phone to somebody nearby"
},
"NoBusinessesWithinRange": "There are no businesses within {1} meters",
"NoHousesWithinRange": "There are no houses within {1} meters",
"NoPayPhonesWithinRange": "There are no payphones within {1} meters",
"HeaderBusinessesInRangeList": "Businesses (within {1} meters)",
"HeaderHousesInRangeList": "Businesses (within {1} meters)",
"HeaderPayPhonesInRangeList": "Businesses (within {1} meters)",
"HeaderCommandsForStaffFlagList": "Admin Commands ({1})",
"PlayerLocateDistanceAndDirection": "{1} is {2} meters {3}",
"MustBeNumber": "You need to use a number!",
"HeaderJobRoutesList": "Job Routes ({1})",
"HeaderJobRouteInfo": "Job Route Information (${1})",
"InvalidJobRoute": "Job route not found!",
"PayPhoneDeleted": "The payphone was deleted",
"PayPhoneAnswer": "Use {1} to answer the payphone",
"ResetActionTipsConfirm": "Are you sure you want to reset all seen action tips?",
"ActionTipsReset": "All seen action tips have been reset.",
"NormalChatDisabled": "Normal chat is disabled by server admin. Use chat commands instead.",
"GlobalChatDisabled": "Global out-of-character chat is disabled by server admin"
}

View File

@@ -16,9 +16,7 @@
"InvalidAnimationDistance": "The distance must be between 0 and 3",
"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",
@@ -653,28 +651,6 @@
"LeftWrist": "Left Wrist",
"RightWrist": "Right Wrist"
},
"ActionTips": {
"VehicleEngineOffWhenEnteringKey": "Use {1} to turn on or off a vehicle's engine",
"VehicleLockedAfterEntryAttempt": "Use {1} to lock or unlock a vehicle",
"ShowItemsAfterPurchase": "Use {1} to see your inventory",
"BuyCommandAfterEnterBusiness": "Use {1} to buy items from a business",
"UseItemKeyAfterEquipping": "Use {1} to use your equipped item",
"UseItemKeyAfterEquippingWalkieTalkie": "Use {1} to turn on or off your radio",
"RadioCommandAfterEnablingWalkieTalkie": "Use {1} to talk on your radio",
"ReplyToDirectMessage": "Use {1} to easily reply to a private message",
"UseItemKeyAmmoAfterEquippingWeapon": "Use {1} to load an ammo item into your equipped weapon",
"AnimationStop": "Use {1} to stop your animation",
"JobEquipmentInventory": "The job equipment is in your inventory. Use {1} to see them.",
"ViewInventory": "Use {1} to see your items",
"VehicleRepairItemUsage": "Stand next to a vehicle and use {1} to repair it",
"VehicleColourItemUsage": "Stand next to a vehicle and use {1} to change it's colour",
"VehiclePartItemUsage": "Stand next to a vehicle and use {1} to upgrade with {2}",
"AmmoClipItemUsage": "Equip the weapon and use {1} to load ammo into it",
"GenericItemUsage": "Use {1} to use the {2}",
"EnterJobVehicleForRoute": "Enter a job vehicle nearby to start a job route",
"JobLocations": "Visit a job location to get a job. Use {1} to find a job location",
"JobRouteStart": "Use {1} to start a job route with this vehicle"
},
"DisconnectReasons": {
"Unknown": "Unknown",
"LostConnection": "Lost Connection",
@@ -750,5 +726,68 @@
"Cancel": "Cancel",
"AlreadyOwnVehicle": "You already own this vehicle!",
"PropertyEntranceFeeLabel": "Entrance Fee: {1}",
"NeedToBeInJobVehicle": "You need to be in a job vehicle!"
"NeedToBeInJobVehicle": "You need to be in a job vehicle!",
"InvalidJobRank": "Job rank not found!",
"NoPlayerCloseEnough": "There is no player close enough!",
"PayPhoneRecipientAnswered": "Somebody answered the call. Use normal chat to talk to them.",
"PayPhoneAnswered": "You answered the phone. Use normal chat to talk to the caller.",
"PayPhoneRecipientHangup": "The line was disconnected. You have been charged {1}",
"PayPhoneHangup": "You hung up the phone.",
"AlreadyUsingPayPhone": "You are already using a payphone!",
"NotUsingPayPhone": "You are not using a payphone!",
"NoPayPhoneCloseEnough": "There is no payphone close enough!",
"PayPhoneNotRinging": "This payphone is not ringing!",
"PayPhoneOccupied": "This payphone is already being used by someone else!",
"PayPhoneOccupantSwitched": "A different voice is now on the line",
"PayPhoneGiven": "You gave the phone to {1}",
"PayPhoneReceived": "{1} gave you the phone",
"PayPhoneUnableToCallPlayer": "You can't call {1} at this time. Please try again later.",
"ActionTips": {
"VehicleEngineOffWhenEnteringKey": "Use {1} to turn on or off a vehicle's engine",
"VehicleLockedAfterEntryAttempt": "Use {1} to lock or unlock a vehicle",
"ShowItemsAfterPurchase": "Use {1} to see your inventory",
"BuyCommandAfterEnterBusiness": "Use {1} to buy items from a business",
"UseItemKeyAfterEquipping": "Use {1} to use your equipped item",
"UseItemKeyAfterEquippingWalkieTalkie": "Use {1} to turn on or off your radio",
"RadioCommandAfterEnablingWalkieTalkie": "Use {1} to talk on your radio",
"ReplyToDirectMessage": "Use {1} to easily reply to a private message",
"UseItemKeyAmmoAfterEquippingWeapon": "Use {1} to load an ammo item into your equipped weapon",
"AnimationStop": "Use {1} to stop your animation",
"JobEquipmentInventory": "The job equipment is in your inventory. Use {1} to see them.",
"ViewInventory": "Use {1} to see your items",
"VehicleRepairItemUsage": "Stand next to a vehicle and use {1} to repair it",
"VehicleColourItemUsage": "Stand next to a vehicle and use {1} to change it's colour",
"VehiclePartItemUsage": "Stand next to a vehicle and use {1} to upgrade with {2}",
"AmmoClipItemUsage": "Equip the weapon and use {1} to load ammo into it",
"GenericItemUsage": "Use {1} to use the {2}",
"EnterJobVehicleForRoute": "Enter a job vehicle nearby to start a job route",
"JobLocations": "Visit a job location to get a job. Use {1} to find a job location",
"JobRouteStart": "Use {1} to start a job route with this vehicle",
"PayPhoneFirstUse": "Use {1} to end the call, and {2} to give the phone to somebody nearby",
"BusinessOwnerHelp": "Use {1} to see commands and information for business owners"
},
"NoBusinessesWithinRange": "There are no businesses within {1} meters",
"NoHousesWithinRange": "There are no houses within {1} meters",
"NoPayPhonesWithinRange": "There are no payphones within {1} meters",
"HeaderBusinessesInRangeList": "Businesses (within {1} meters)",
"HeaderHousesInRangeList": "Businesses (within {1} meters)",
"HeaderPayPhonesInRangeList": "Businesses (within {1} meters)",
"HeaderCommandsForStaffFlagList": "Admin Commands ({1})",
"PlayerLocateDistanceAndDirection": "{1} is {2} meters {3}",
"MustBeNumber": "You need to use a number!",
"HeaderJobRoutesList": "Job Routes ({1})",
"HeaderJobRouteInfo": "Job Route Information (${1})",
"InvalidJobRoute": "Job route not found!",
"PayPhoneDeleted": "The payphone was deleted",
"PayPhoneAnswer": "Use {1} to answer the payphone",
"ResetActionTipsConfirm": "Are you sure you want to reset all seen action tips?",
"ActionTipsReset": "All seen action tips have been reset.",
"NormalChatDisabled": "Normal chat is disabled by server admin. Use chat commands instead.",
"GlobalChatDisabled": "Global out-of-character chat is disabled by server admin",
"GUIAlertTitle": "Alert!",
"JobInviteSent": "You sent a job invite to {1}",
"JobInviteAlreadyHasJob": "That player already has a job!",
"JobInviteRequest": "{1} invited you to the {2} job.",
"CantAddJobMembers": "You can't invite new members to the job!",
"CantRemoveJobMembers": "You can't remove members from the job!"
}

View File

@@ -16,12 +16,9 @@
"InvalidAnimationDistance": "etäisyyden pitää olla väliin 0 ja 3",
"CantBanClient": "Sinä et voi bannätä tätä pelaajaa",
"PlayerAccountBanned": "{1} Käyttäjä on nyt bannätty",
"ClanNotFound": "Claania ei löydetty",
"ClanNameTaken": "Claani tuolla nimellä on jo otettu",
"PlayerNotFound": "Pelaajaa ei löytynyt ",
"ClanCantRemoveRanks": "Sinä et voi poistaa tämän claanin rankkejä",
"ClanCantAddRanks": "sinä et voi lisätä claani ranksejä",
"ClanRankNotFound": "Claanin nimeä ei loytynyt",
"ClanCantChangeMemberTag": " Sinä et voi vaihtaa claanin jäsenen tagejä",
"ClanPlayerNotInSameClan": "Tuo pelaaja ei ole sinun claanissa.",
"ClanCantChangeRankLevel": "Sinä et voi vaihtaa claanin rankin leveleitä",
@@ -650,28 +647,6 @@
"LeftWrist": "Vasempi Ranne",
"RightWrist": "Oikeampi Ranne"
},
"ActionTips": {
"VehicleEngineOffWhenEnteringKey": "Käytä {1} laittaksesi päälle tai kiinni ajoneuvon moottori",
"VehicleLockedAfterEntryAttempt": "Käytä {1} Lukitaaksesi tai aukaaksesi ajoneuvosi",
"ShowItemsAfterPurchase": "Käytä {1} Nähdääksesi Tavarasi",
"BuyCommandAfterEnterBusiness": "Käytä {1} tuotteiden ostamiseen yrityksestä",
"UseItemKeyAfterEquipping": "Käytä {1} käyttääksesi varustetasi",
"UseItemKeyAfterEquippingWalkieTalkie": "Käytä {1} kytkeäksesi radion päälle tai pois",
"RadioCommandAfterEnablingWalkieTalkie": "Käytä {1} puhuaksesi radiossasi",
"ReplyToDirectMessage": "Käytä {1} vastataksesi helposti yksityisviestiin",
"UseItemKeyAmmoAfterEquippingWeapon": "Käytä {1} ladataksesi ammuksia varustetulle aseesesi",
"AnimationStop": "Pysäytä animaatio painamalla {1}",
"JobEquipmentInventory": "Työvälineet ovat varastossasi. Käytä {1} nähdäksesi ne.",
"ViewInventory": "Käytä {1} nähdäksesi kohteesi",
"VehicleRepairItemUsage": "Seiso ajoneuvon vieressä ja käytä {1} Korjaaksesi sen",
"VehicleColourItemUsage": "Seiso ajoneuvon vieressä ja käytä {1} Vaihtaaksesi sen väriä",
"VehiclePartItemUsage": "Seiso ajoneuvon vieressä ja käytä {1} tuunatakseen {2}",
"AmmoClipItemUsage": "Varusta ase ja käytä {1} ladataaksesi panoksia",
"GenericItemUsage": "Käytä {1} käyttääksesi {2}",
"EnterJobVehicleForRoute": "Enter a job vehicle nearby to start a job route",
"JobLocations": "Visit a job location to get a job. Use {1} to find a job location",
"JobRouteStart": "Use {1} to start a job route with this vehicle"
},
"DisconnectReasons": {
"Unknown": "Tuntematon",
"LostConnection": "Yhteys menetetty",
@@ -747,5 +722,60 @@
"Cancel": "Cancel",
"AlreadyOwnVehicle": "You already own this vehicle!",
"PropertyEntranceFeeLabel": "Entrance Fee: {1}",
"NeedToBeInJobVehicle": "You need to be in a job vehicle!"
"NeedToBeInJobVehicle": "You need to be in a job vehicle!",
"InvalidJobRank": "Job rank not found!",
"PayPhoneRecipientAnswered": "Somebody answered the call. Use normal chat to talk to them.",
"PayPhoneAnswered": "You answered the phone. Use normal chat to talk to the caller.",
"PayPhoneRecipientHangup": "The line was disconnected. You have been charged {1}",
"PayPhoneHangup": "You hung up the phone.",
"AlreadyUsingPayPhone": "You are already using a payphone!",
"NotUsingPayPhone": "You are not using a payphone!",
"NoPayPhoneCloseEnough": "There is no payphone close enough!",
"PayPhoneNotRinging": "This payphone is not ringing!",
"PayPhoneOccupied": "This payphone is already being used by someone else!",
"PayPhoneOccupantSwitched": "A different voice is now on the line",
"PayPhoneGiven": "You gave the phone to {1}",
"PayPhoneReceived": "{1} gave you the phone",
"PayPhoneUnableToCallPlayer": "You can't call {1} at this time. Please try again later.",
"ActionTips": {
"VehicleEngineOffWhenEnteringKey": "Käytä {1} laittaksesi päälle tai kiinni ajoneuvon moottori",
"VehicleLockedAfterEntryAttempt": "Käytä {1} Lukitaaksesi tai aukaaksesi ajoneuvosi",
"ShowItemsAfterPurchase": "Käytä {1} Nähdääksesi Tavarasi",
"BuyCommandAfterEnterBusiness": "Käytä {1} tuotteiden ostamiseen yrityksestä",
"UseItemKeyAfterEquipping": "Käytä {1} käyttääksesi varustetasi",
"UseItemKeyAfterEquippingWalkieTalkie": "Käytä {1} kytkeäksesi radion päälle tai pois",
"RadioCommandAfterEnablingWalkieTalkie": "Käytä {1} puhuaksesi radiossasi",
"ReplyToDirectMessage": "Käytä {1} vastataksesi helposti yksityisviestiin",
"UseItemKeyAmmoAfterEquippingWeapon": "Käytä {1} ladataksesi ammuksia varustetulle aseesesi",
"AnimationStop": "Pysäytä animaatio painamalla {1}",
"JobEquipmentInventory": "Työvälineet ovat varastossasi. Käytä {1} nähdäksesi ne.",
"ViewInventory": "Käytä {1} nähdäksesi kohteesi",
"VehicleRepairItemUsage": "Seiso ajoneuvon vieressä ja käytä {1} Korjaaksesi sen",
"VehicleColourItemUsage": "Seiso ajoneuvon vieressä ja käytä {1} Vaihtaaksesi sen väriä",
"VehiclePartItemUsage": "Seiso ajoneuvon vieressä ja käytä {1} tuunatakseen {2}",
"AmmoClipItemUsage": "Varusta ase ja käytä {1} ladataaksesi panoksia",
"GenericItemUsage": "Käytä {1} käyttääksesi {2}",
"EnterJobVehicleForRoute": "Enter a job vehicle nearby to start a job route",
"JobLocations": "Visit a job location to get a job. Use {1} to find a job location",
"JobRouteStart": "Use {1} to start a job route with this vehicle",
"PayPhoneFirstUse": "Use {1} to end the call, and {2} to give the phone to somebody nearby"
},
"NoBusinessesWithinRange": "There are no businesses within {1} meters",
"NoHousesWithinRange": "There are no houses within {1} meters",
"NoPayPhonesWithinRange": "There are no payphones within {1} meters",
"HeaderBusinessesInRangeList": "Businesses (within {1} meters)",
"HeaderHousesInRangeList": "Businesses (within {1} meters)",
"HeaderPayPhonesInRangeList": "Businesses (within {1} meters)",
"HeaderCommandsForStaffFlagList": "Admin Commands ({1})",
"PlayerLocateDistanceAndDirection": "{1} is {2} meters {3}",
"MustBeNumber": "You need to use a number!",
"HeaderJobRoutesList": "Job Routes ({1})",
"HeaderJobRouteInfo": "Job Route Information (${1})",
"InvalidJobRoute": "Job route not found!",
"PayPhoneDeleted": "The payphone was deleted",
"PayPhoneAnswer": "Use {1} to answer the payphone",
"ResetActionTipsConfirm": "Are you sure you want to reset all seen action tips?",
"ActionTipsReset": "All seen action tips have been reset.",
"NormalChatDisabled": "Normal chat is disabled by server admin. Use chat commands instead.",
"GlobalChatDisabled": "Global out-of-character chat is disabled by server admin"
}

View File

@@ -16,12 +16,9 @@
"InvalidAnimationDistance": "La distance doit être entre 0 et 3",
"CantBanClient": "Vous ne pouvez pas bannir cette personne",
"PlayerAccountBanned": "le compte {1} a été banni",
"ClanNotFound": "Clan non trouvé",
"ClanNameTaken": "Un clan avec ce nom existe déjà",
"PlayerNotFound": "Joueur non trouvé",
"ClanCantRemoveRanks": "Vous ne pouvez pas retirer le rang du clan",
"ClanCantAddRanks": "Vous ne pouvez pas ajouter de rang au clan",
"ClanRankNotFound": "Le rang du clan est introuvable",
"ClanCantChangeMemberTag": "Vous ne pouvez pas modifier les tags des membres du clan",
"ClanPlayerNotInSameClan": "Ce joueur n'est pas dans votre clan",
"ClanCantChangeRankLevel": "Vous ne pouvez pas modifier le niveau du rang du clan",
@@ -651,28 +648,6 @@
"LeftWrist": "Left Wrist",
"RightWrist": "Right Wrist"
},
"ActionTips": {
"VehicleEngineOffWhenEnteringKey": "Use {1} to turn on or off a vehicle's engine",
"VehicleLockedAfterEntryAttempt": "Use {1} to lock or unlock a vehicle",
"ShowItemsAfterPurchase": "Use {1} to see your inventory",
"BuyCommandAfterEnterBusiness": "Use {1} to buy items from a business",
"UseItemKeyAfterEquipping": "Use {1} to use your equipped item",
"UseItemKeyAfterEquippingWalkieTalkie": "Use {1} to turn on or off your radio",
"RadioCommandAfterEnablingWalkieTalkie": "Use {1} to talk on your radio",
"ReplyToDirectMessage": "Use {1} to easily reply to a private message",
"UseItemKeyAmmoAfterEquippingWeapon": "Use {1} to load an ammo item into your equipped weapon",
"AnimationStop": "Use {1} to stop your animation",
"JobEquipmentInventory": "The job equipment is in your inventory. Use {1} to see them.",
"ViewInventory": "Use {1} to see your items",
"VehicleRepairItemUsage": "Stand next to a vehicle and use {1} to repair it",
"VehicleColourItemUsage": "Stand next to a vehicle and use {1} to change it's colour",
"VehiclePartItemUsage": "Stand next to a vehicle and use {1} to upgrade with {2}",
"AmmoClipItemUsage": "Equip the weapon and use {1} to load ammo into it",
"GenericItemUsage": "Use {1} to use the {2}",
"EnterJobVehicleForRoute": "Enter a job vehicle nearby to start a job route",
"JobLocations": "Visit a job location to get a job. Use {1} to find a job location",
"JobRouteStart": "Use {1} to start a job route with this vehicle"
},
"DisconnectReasons": {
"Unknown": "Unknown",
"LostConnection": "Lost Connection",
@@ -748,5 +723,60 @@
"Cancel": "Cancel",
"AlreadyOwnVehicle": "You already own this vehicle!",
"PropertyEntranceFeeLabel": "Entrance Fee: {1}",
"NeedToBeInJobVehicle": "You need to be in a job vehicle!"
"NeedToBeInJobVehicle": "You need to be in a job vehicle!",
"InvalidJobRank": "Job rank not found!",
"PayPhoneRecipientAnswered": "Somebody answered the call. Use normal chat to talk to them.",
"PayPhoneAnswered": "You answered the phone. Use normal chat to talk to the caller.",
"PayPhoneRecipientHangup": "The line was disconnected. You have been charged {1}",
"PayPhoneHangup": "You hung up the phone.",
"AlreadyUsingPayPhone": "You are already using a payphone!",
"NotUsingPayPhone": "You are not using a payphone!",
"NoPayPhoneCloseEnough": "There is no payphone close enough!",
"PayPhoneNotRinging": "This payphone is not ringing!",
"PayPhoneOccupied": "This payphone is already being used by someone else!",
"PayPhoneOccupantSwitched": "A different voice is now on the line",
"PayPhoneGiven": "You gave the phone to {1}",
"PayPhoneReceived": "{1} gave you the phone",
"PayPhoneUnableToCallPlayer": "You can't call {1} at this time. Please try again later.",
"ActionTips": {
"VehicleEngineOffWhenEnteringKey": "Use {1} to turn on or off a vehicle's engine",
"VehicleLockedAfterEntryAttempt": "Use {1} to lock or unlock a vehicle",
"ShowItemsAfterPurchase": "Use {1} to see your inventory",
"BuyCommandAfterEnterBusiness": "Use {1} to buy items from a business",
"UseItemKeyAfterEquipping": "Use {1} to use your equipped item",
"UseItemKeyAfterEquippingWalkieTalkie": "Use {1} to turn on or off your radio",
"RadioCommandAfterEnablingWalkieTalkie": "Use {1} to talk on your radio",
"ReplyToDirectMessage": "Use {1} to easily reply to a private message",
"UseItemKeyAmmoAfterEquippingWeapon": "Use {1} to load an ammo item into your equipped weapon",
"AnimationStop": "Use {1} to stop your animation",
"JobEquipmentInventory": "The job equipment is in your inventory. Use {1} to see them.",
"ViewInventory": "Use {1} to see your items",
"VehicleRepairItemUsage": "Stand next to a vehicle and use {1} to repair it",
"VehicleColourItemUsage": "Stand next to a vehicle and use {1} to change it's colour",
"VehiclePartItemUsage": "Stand next to a vehicle and use {1} to upgrade with {2}",
"AmmoClipItemUsage": "Equip the weapon and use {1} to load ammo into it",
"GenericItemUsage": "Use {1} to use the {2}",
"EnterJobVehicleForRoute": "Enter a job vehicle nearby to start a job route",
"JobLocations": "Visit a job location to get a job. Use {1} to find a job location",
"JobRouteStart": "Use {1} to start a job route with this vehicle",
"PayPhoneFirstUse": "Use {1} to end the call, and {2} to give the phone to somebody nearby"
},
"NoBusinessesWithinRange": "There are no businesses within {1} meters",
"NoHousesWithinRange": "There are no houses within {1} meters",
"NoPayPhonesWithinRange": "There are no payphones within {1} meters",
"HeaderBusinessesInRangeList": "Businesses (within {1} meters)",
"HeaderHousesInRangeList": "Businesses (within {1} meters)",
"HeaderPayPhonesInRangeList": "Businesses (within {1} meters)",
"HeaderCommandsForStaffFlagList": "Admin Commands ({1})",
"PlayerLocateDistanceAndDirection": "{1} is {2} meters {3}",
"MustBeNumber": "You need to use a number!",
"HeaderJobRoutesList": "Job Routes ({1})",
"HeaderJobRouteInfo": "Job Route Information (${1})",
"InvalidJobRoute": "Job route not found!",
"PayPhoneDeleted": "The payphone was deleted",
"PayPhoneAnswer": "Use {1} to answer the payphone",
"ResetActionTipsConfirm": "Are you sure you want to reset all seen action tips?",
"ActionTipsReset": "All seen action tips have been reset.",
"NormalChatDisabled": "Normal chat is disabled by server admin. Use chat commands instead.",
"GlobalChatDisabled": "Global out-of-character chat is disabled by server admin"
}

View File

@@ -16,12 +16,9 @@
"InvalidAnimationDistance": "The distance must be between 0 and 3",
"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",
@@ -650,28 +647,6 @@
"LeftWrist": "Left Wrist",
"RightWrist": "Right Wrist"
},
"ActionTips": {
"VehicleEngineOffWhenEnteringKey": "Use {1} to turn on or off a vehicle's engine",
"VehicleLockedAfterEntryAttempt": "Use {1} to lock or unlock a vehicle",
"ShowItemsAfterPurchase": "Use {1} to see your inventory",
"BuyCommandAfterEnterBusiness": "Use {1} to buy items from a business",
"UseItemKeyAfterEquipping": "Use {1} to use your equipped item",
"UseItemKeyAfterEquippingWalkieTalkie": "Use {1} to turn on or off your radio",
"RadioCommandAfterEnablingWalkieTalkie": "Use {1} to talk on your radio",
"ReplyToDirectMessage": "Use {1} to easily reply to a private message",
"UseItemKeyAmmoAfterEquippingWeapon": "Use {1} to load an ammo item into your equipped weapon",
"AnimationStop": "Use {1} to stop your animation",
"JobEquipmentInventory": "The job equipment is in your inventory. Use {1} to see them.",
"ViewInventory": "Use {1} to see your items",
"VehicleRepairItemUsage": "Stand next to a vehicle and use {1} to repair it",
"VehicleColourItemUsage": "Stand next to a vehicle and use {1} to change it's colour",
"VehiclePartItemUsage": "Stand next to a vehicle and use {1} to upgrade with {2}",
"AmmoClipItemUsage": "Equip the weapon and use {1} to load ammo into it",
"GenericItemUsage": "Use {1} to use the {2}",
"EnterJobVehicleForRoute": "Enter a job vehicle nearby to start a job route",
"JobLocations": "Visit a job location to get a job. Use {1} to find a job location",
"JobRouteStart": "Use {1} to start a job route with this vehicle"
},
"DisconnectReasons": {
"Unknown": "Unknown",
"LostConnection": "Lost Connection",
@@ -747,5 +722,60 @@
"Cancel": "Cancel",
"AlreadyOwnVehicle": "You already own this vehicle!",
"PropertyEntranceFeeLabel": "Entrance Fee: {1}",
"NeedToBeInJobVehicle": "You need to be in a job vehicle!"
"NeedToBeInJobVehicle": "You need to be in a job vehicle!",
"InvalidJobRank": "Job rank not found!",
"PayPhoneRecipientAnswered": "Somebody answered the call. Use normal chat to talk to them.",
"PayPhoneAnswered": "You answered the phone. Use normal chat to talk to the caller.",
"PayPhoneRecipientHangup": "The line was disconnected. You have been charged {1}",
"PayPhoneHangup": "You hung up the phone.",
"AlreadyUsingPayPhone": "You are already using a payphone!",
"NotUsingPayPhone": "You are not using a payphone!",
"NoPayPhoneCloseEnough": "There is no payphone close enough!",
"PayPhoneNotRinging": "This payphone is not ringing!",
"PayPhoneOccupied": "This payphone is already being used by someone else!",
"PayPhoneOccupantSwitched": "A different voice is now on the line",
"PayPhoneGiven": "You gave the phone to {1}",
"PayPhoneReceived": "{1} gave you the phone",
"PayPhoneUnableToCallPlayer": "You can't call {1} at this time. Please try again later.",
"ActionTips": {
"VehicleEngineOffWhenEnteringKey": "Use {1} to turn on or off a vehicle's engine",
"VehicleLockedAfterEntryAttempt": "Use {1} to lock or unlock a vehicle",
"ShowItemsAfterPurchase": "Use {1} to see your inventory",
"BuyCommandAfterEnterBusiness": "Use {1} to buy items from a business",
"UseItemKeyAfterEquipping": "Use {1} to use your equipped item",
"UseItemKeyAfterEquippingWalkieTalkie": "Use {1} to turn on or off your radio",
"RadioCommandAfterEnablingWalkieTalkie": "Use {1} to talk on your radio",
"ReplyToDirectMessage": "Use {1} to easily reply to a private message",
"UseItemKeyAmmoAfterEquippingWeapon": "Use {1} to load an ammo item into your equipped weapon",
"AnimationStop": "Use {1} to stop your animation",
"JobEquipmentInventory": "The job equipment is in your inventory. Use {1} to see them.",
"ViewInventory": "Use {1} to see your items",
"VehicleRepairItemUsage": "Stand next to a vehicle and use {1} to repair it",
"VehicleColourItemUsage": "Stand next to a vehicle and use {1} to change it's colour",
"VehiclePartItemUsage": "Stand next to a vehicle and use {1} to upgrade with {2}",
"AmmoClipItemUsage": "Equip the weapon and use {1} to load ammo into it",
"GenericItemUsage": "Use {1} to use the {2}",
"EnterJobVehicleForRoute": "Enter a job vehicle nearby to start a job route",
"JobLocations": "Visit a job location to get a job. Use {1} to find a job location",
"JobRouteStart": "Use {1} to start a job route with this vehicle",
"PayPhoneFirstUse": "Use {1} to end the call, and {2} to give the phone to somebody nearby"
},
"NoBusinessesWithinRange": "There are no businesses within {1} meters",
"NoHousesWithinRange": "There are no houses within {1} meters",
"NoPayPhonesWithinRange": "There are no payphones within {1} meters",
"HeaderBusinessesInRangeList": "Businesses (within {1} meters)",
"HeaderHousesInRangeList": "Businesses (within {1} meters)",
"HeaderPayPhonesInRangeList": "Businesses (within {1} meters)",
"HeaderCommandsForStaffFlagList": "Admin Commands ({1})",
"PlayerLocateDistanceAndDirection": "{1} is {2} meters {3}",
"MustBeNumber": "You need to use a number!",
"HeaderJobRoutesList": "Job Routes ({1})",
"HeaderJobRouteInfo": "Job Route Information (${1})",
"InvalidJobRoute": "Job route not found!",
"PayPhoneDeleted": "The payphone was deleted",
"PayPhoneAnswer": "Use {1} to answer the payphone",
"ResetActionTipsConfirm": "Are you sure you want to reset all seen action tips?",
"ActionTipsReset": "All seen action tips have been reset.",
"NormalChatDisabled": "Normal chat is disabled by server admin. Use chat commands instead.",
"GlobalChatDisabled": "Global out-of-character chat is disabled by server admin"
}

View File

@@ -16,12 +16,9 @@
"InvalidAnimationDistance": "The distance must be between 0 and 3",
"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",
@@ -651,28 +648,6 @@
"LeftWrist": "Left Wrist",
"RightWrist": "Right Wrist"
},
"ActionTips": {
"VehicleEngineOffWhenEnteringKey": "Use {1} to turn on or off a vehicle's engine",
"VehicleLockedAfterEntryAttempt": "Use {1} to lock or unlock a vehicle",
"ShowItemsAfterPurchase": "Use {1} to see your inventory",
"BuyCommandAfterEnterBusiness": "Use {1} to buy items from a business",
"UseItemKeyAfterEquipping": "Use {1} to use your equipped item",
"UseItemKeyAfterEquippingWalkieTalkie": "Use {1} to turn on or off your radio",
"RadioCommandAfterEnablingWalkieTalkie": "Use {1} to talk on your radio",
"ReplyToDirectMessage": "Use {1} to easily reply to a private message",
"UseItemKeyAmmoAfterEquippingWeapon": "Use {1} to load an ammo item into your equipped weapon",
"AnimationStop": "Use {1} to stop your animation",
"JobEquipmentInventory": "The job equipment is in your inventory. Use {1} to see them.",
"ViewInventory": "Use {1} to see your items",
"VehicleRepairItemUsage": "Stand next to a vehicle and use {1} to repair it",
"VehicleColourItemUsage": "Stand next to a vehicle and use {1} to change it's colour",
"VehiclePartItemUsage": "Stand next to a vehicle and use {1} to upgrade with {2}",
"AmmoClipItemUsage": "Equip the weapon and use {1} to load ammo into it",
"GenericItemUsage": "Use {1} to use the {2}",
"EnterJobVehicleForRoute": "Enter a job vehicle nearby to start a job route",
"JobLocations": "Visit a job location to get a job. Use {1} to find a job location",
"JobRouteStart": "Use {1} to start a job route with this vehicle"
},
"DisconnectReasons": {
"Unknown": "Unknown",
"LostConnection": "Lost Connection",
@@ -748,5 +723,60 @@
"Cancel": "Cancel",
"AlreadyOwnVehicle": "You already own this vehicle!",
"PropertyEntranceFeeLabel": "Entrance Fee: {1}",
"NeedToBeInJobVehicle": "You need to be in a job vehicle!"
"NeedToBeInJobVehicle": "You need to be in a job vehicle!",
"InvalidJobRank": "Job rank not found!",
"PayPhoneRecipientAnswered": "Somebody answered the call. Use normal chat to talk to them.",
"PayPhoneAnswered": "You answered the phone. Use normal chat to talk to the caller.",
"PayPhoneRecipientHangup": "The line was disconnected. You have been charged {1}",
"PayPhoneHangup": "You hung up the phone.",
"AlreadyUsingPayPhone": "You are already using a payphone!",
"NotUsingPayPhone": "You are not using a payphone!",
"NoPayPhoneCloseEnough": "There is no payphone close enough!",
"PayPhoneNotRinging": "This payphone is not ringing!",
"PayPhoneOccupied": "This payphone is already being used by someone else!",
"PayPhoneOccupantSwitched": "A different voice is now on the line",
"PayPhoneGiven": "You gave the phone to {1}",
"PayPhoneReceived": "{1} gave you the phone",
"PayPhoneUnableToCallPlayer": "You can't call {1} at this time. Please try again later.",
"ActionTips": {
"VehicleEngineOffWhenEnteringKey": "Use {1} to turn on or off a vehicle's engine",
"VehicleLockedAfterEntryAttempt": "Use {1} to lock or unlock a vehicle",
"ShowItemsAfterPurchase": "Use {1} to see your inventory",
"BuyCommandAfterEnterBusiness": "Use {1} to buy items from a business",
"UseItemKeyAfterEquipping": "Use {1} to use your equipped item",
"UseItemKeyAfterEquippingWalkieTalkie": "Use {1} to turn on or off your radio",
"RadioCommandAfterEnablingWalkieTalkie": "Use {1} to talk on your radio",
"ReplyToDirectMessage": "Use {1} to easily reply to a private message",
"UseItemKeyAmmoAfterEquippingWeapon": "Use {1} to load an ammo item into your equipped weapon",
"AnimationStop": "Use {1} to stop your animation",
"JobEquipmentInventory": "The job equipment is in your inventory. Use {1} to see them.",
"ViewInventory": "Use {1} to see your items",
"VehicleRepairItemUsage": "Stand next to a vehicle and use {1} to repair it",
"VehicleColourItemUsage": "Stand next to a vehicle and use {1} to change it's colour",
"VehiclePartItemUsage": "Stand next to a vehicle and use {1} to upgrade with {2}",
"AmmoClipItemUsage": "Equip the weapon and use {1} to load ammo into it",
"GenericItemUsage": "Use {1} to use the {2}",
"EnterJobVehicleForRoute": "Enter a job vehicle nearby to start a job route",
"JobLocations": "Visit a job location to get a job. Use {1} to find a job location",
"JobRouteStart": "Use {1} to start a job route with this vehicle",
"PayPhoneFirstUse": "Use {1} to end the call, and {2} to give the phone to somebody nearby"
},
"NoBusinessesWithinRange": "There are no businesses within {1} meters",
"NoHousesWithinRange": "There are no houses within {1} meters",
"NoPayPhonesWithinRange": "There are no payphones within {1} meters",
"HeaderBusinessesInRangeList": "Businesses (within {1} meters)",
"HeaderHousesInRangeList": "Businesses (within {1} meters)",
"HeaderPayPhonesInRangeList": "Businesses (within {1} meters)",
"HeaderCommandsForStaffFlagList": "Admin Commands ({1})",
"PlayerLocateDistanceAndDirection": "{1} is {2} meters {3}",
"MustBeNumber": "You need to use a number!",
"HeaderJobRoutesList": "Job Routes ({1})",
"HeaderJobRouteInfo": "Job Route Information (${1})",
"InvalidJobRoute": "Job route not found!",
"PayPhoneDeleted": "The payphone was deleted",
"PayPhoneAnswer": "Use {1} to answer the payphone",
"ResetActionTipsConfirm": "Are you sure you want to reset all seen action tips?",
"ActionTipsReset": "All seen action tips have been reset.",
"NormalChatDisabled": "Normal chat is disabled by server admin. Use chat commands instead.",
"GlobalChatDisabled": "Global out-of-character chat is disabled by server admin"
}

View File

@@ -16,12 +16,9 @@
"InvalidAnimationDistance": "The distance must be between 0 and 3",
"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",
@@ -653,28 +650,6 @@
"LeftWrist": "Left Wrist",
"RightWrist": "Right Wrist"
},
"ActionTips": {
"VehicleEngineOffWhenEnteringKey": "Use {1} to turn on or off a vehicle's engine",
"VehicleLockedAfterEntryAttempt": "Use {1} to lock or unlock a vehicle",
"ShowItemsAfterPurchase": "Use {1} to see your inventory",
"BuyCommandAfterEnterBusiness": "Use {1} to buy items from a business",
"UseItemKeyAfterEquipping": "Use {1} to use your equipped item",
"UseItemKeyAfterEquippingWalkieTalkie": "Use {1} to turn on or off your radio",
"RadioCommandAfterEnablingWalkieTalkie": "Use {1} to talk on your radio",
"ReplyToDirectMessage": "Use {1} to easily reply to a private message",
"UseItemKeyAmmoAfterEquippingWeapon": "Use {1} to load an ammo item into your equipped weapon",
"AnimationStop": "Use {1} to stop your animation",
"JobEquipmentInventory": "The job equipment is in your inventory. Use {1} to see them.",
"ViewInventory": "Use {1} to see your items",
"VehicleRepairItemUsage": "Stand next to a vehicle and use {1} to repair it",
"VehicleColourItemUsage": "Stand next to a vehicle and use {1} to change it's colour",
"VehiclePartItemUsage": "Stand next to a vehicle and use {1} to upgrade with {2}",
"AmmoClipItemUsage": "Equip the weapon and use {1} to load ammo into it",
"GenericItemUsage": "Use {1} to use the {2}",
"EnterJobVehicleForRoute": "Enter a job vehicle nearby to start a job route",
"JobLocations": "Visit a job location to get a job. Use {1} to find a job location",
"JobRouteStart": "Use {1} to start a job route with this vehicle"
},
"DisconnectReasons": {
"Unknown": "Unknown",
"LostConnection": "Lost Connection",
@@ -750,5 +725,60 @@
"Cancel": "Cancel",
"AlreadyOwnVehicle": "You already own this vehicle!",
"PropertyEntranceFeeLabel": "Entrance Fee: {1}",
"NeedToBeInJobVehicle": "You need to be in a job vehicle!"
"NeedToBeInJobVehicle": "You need to be in a job vehicle!",
"InvalidJobRank": "Job rank not found!",
"PayPhoneRecipientAnswered": "Somebody answered the call. Use normal chat to talk to them.",
"PayPhoneAnswered": "You answered the phone. Use normal chat to talk to the caller.",
"PayPhoneRecipientHangup": "The line was disconnected. You have been charged {1}",
"PayPhoneHangup": "You hung up the phone.",
"AlreadyUsingPayPhone": "You are already using a payphone!",
"NotUsingPayPhone": "You are not using a payphone!",
"NoPayPhoneCloseEnough": "There is no payphone close enough!",
"PayPhoneNotRinging": "This payphone is not ringing!",
"PayPhoneOccupied": "This payphone is already being used by someone else!",
"PayPhoneOccupantSwitched": "A different voice is now on the line",
"PayPhoneGiven": "You gave the phone to {1}",
"PayPhoneReceived": "{1} gave you the phone",
"PayPhoneUnableToCallPlayer": "You can't call {1} at this time. Please try again later.",
"ActionTips": {
"VehicleEngineOffWhenEnteringKey": "Use {1} to turn on or off a vehicle's engine",
"VehicleLockedAfterEntryAttempt": "Use {1} to lock or unlock a vehicle",
"ShowItemsAfterPurchase": "Use {1} to see your inventory",
"BuyCommandAfterEnterBusiness": "Use {1} to buy items from a business",
"UseItemKeyAfterEquipping": "Use {1} to use your equipped item",
"UseItemKeyAfterEquippingWalkieTalkie": "Use {1} to turn on or off your radio",
"RadioCommandAfterEnablingWalkieTalkie": "Use {1} to talk on your radio",
"ReplyToDirectMessage": "Use {1} to easily reply to a private message",
"UseItemKeyAmmoAfterEquippingWeapon": "Use {1} to load an ammo item into your equipped weapon",
"AnimationStop": "Use {1} to stop your animation",
"JobEquipmentInventory": "The job equipment is in your inventory. Use {1} to see them.",
"ViewInventory": "Use {1} to see your items",
"VehicleRepairItemUsage": "Stand next to a vehicle and use {1} to repair it",
"VehicleColourItemUsage": "Stand next to a vehicle and use {1} to change it's colour",
"VehiclePartItemUsage": "Stand next to a vehicle and use {1} to upgrade with {2}",
"AmmoClipItemUsage": "Equip the weapon and use {1} to load ammo into it",
"GenericItemUsage": "Use {1} to use the {2}",
"EnterJobVehicleForRoute": "Enter a job vehicle nearby to start a job route",
"JobLocations": "Visit a job location to get a job. Use {1} to find a job location",
"JobRouteStart": "Use {1} to start a job route with this vehicle",
"PayPhoneFirstUse": "Use {1} to end the call, and {2} to give the phone to somebody nearby"
},
"NoBusinessesWithinRange": "There are no businesses within {1} meters",
"NoHousesWithinRange": "There are no houses within {1} meters",
"NoPayPhonesWithinRange": "There are no payphones within {1} meters",
"HeaderBusinessesInRangeList": "Businesses (within {1} meters)",
"HeaderHousesInRangeList": "Businesses (within {1} meters)",
"HeaderPayPhonesInRangeList": "Businesses (within {1} meters)",
"HeaderCommandsForStaffFlagList": "Admin Commands ({1})",
"PlayerLocateDistanceAndDirection": "{1} is {2} meters {3}",
"MustBeNumber": "You need to use a number!",
"HeaderJobRoutesList": "Job Routes ({1})",
"HeaderJobRouteInfo": "Job Route Information (${1})",
"InvalidJobRoute": "Job route not found!",
"PayPhoneDeleted": "The payphone was deleted",
"PayPhoneAnswer": "Use {1} to answer the payphone",
"ResetActionTipsConfirm": "Are you sure you want to reset all seen action tips?",
"ActionTipsReset": "All seen action tips have been reset.",
"NormalChatDisabled": "Normal chat is disabled by server admin. Use chat commands instead.",
"GlobalChatDisabled": "Global out-of-character chat is disabled by server admin"
}

View File

@@ -16,12 +16,9 @@
"InvalidAnimationDistance": "The distance must be between 0 and 3",
"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",
@@ -652,28 +649,6 @@
"LeftWrist": "Left Wrist",
"RightWrist": "Right Wrist"
},
"ActionTips": {
"VehicleEngineOffWhenEnteringKey": "Use {1} to turn on or off a vehicle's engine",
"VehicleLockedAfterEntryAttempt": "Use {1} to lock or unlock a vehicle",
"ShowItemsAfterPurchase": "Use {1} to see your inventory",
"BuyCommandAfterEnterBusiness": "Use {1} to buy items from a business",
"UseItemKeyAfterEquipping": "Use {1} to use your equipped item",
"UseItemKeyAfterEquippingWalkieTalkie": "Use {1} to turn on or off your radio",
"RadioCommandAfterEnablingWalkieTalkie": "Use {1} to talk on your radio",
"ReplyToDirectMessage": "Use {1} to easily reply to a private message",
"UseItemKeyAmmoAfterEquippingWeapon": "Use {1} to load an ammo item into your equipped weapon",
"AnimationStop": "Use {1} to stop your animation",
"JobEquipmentInventory": "The job equipment is in your inventory. Use {1} to see them.",
"ViewInventory": "Use {1} to see your items",
"VehicleRepairItemUsage": "Stand next to a vehicle and use {1} to repair it",
"VehicleColourItemUsage": "Stand next to a vehicle and use {1} to change it's colour",
"VehiclePartItemUsage": "Stand next to a vehicle and use {1} to upgrade with {2}",
"AmmoClipItemUsage": "Equip the weapon and use {1} to load ammo into it",
"GenericItemUsage": "Use {1} to use the {2}",
"EnterJobVehicleForRoute": "Enter a job vehicle nearby to start a job route",
"JobLocations": "Visit a job location to get a job. Use {1} to find a job location",
"JobRouteStart": "Use {1} to start a job route with this vehicle"
},
"DisconnectReasons": {
"Unknown": "Unknown",
"LostConnection": "Lost Connection",
@@ -749,5 +724,60 @@
"Cancel": "Cancel",
"AlreadyOwnVehicle": "You already own this vehicle!",
"PropertyEntranceFeeLabel": "Entrance Fee: {1}",
"NeedToBeInJobVehicle": "You need to be in a job vehicle!"
"NeedToBeInJobVehicle": "You need to be in a job vehicle!",
"InvalidJobRank": "Job rank not found!",
"PayPhoneRecipientAnswered": "Somebody answered the call. Use normal chat to talk to them.",
"PayPhoneAnswered": "You answered the phone. Use normal chat to talk to the caller.",
"PayPhoneRecipientHangup": "The line was disconnected. You have been charged {1}",
"PayPhoneHangup": "You hung up the phone.",
"AlreadyUsingPayPhone": "You are already using a payphone!",
"NotUsingPayPhone": "You are not using a payphone!",
"NoPayPhoneCloseEnough": "There is no payphone close enough!",
"PayPhoneNotRinging": "This payphone is not ringing!",
"PayPhoneOccupied": "This payphone is already being used by someone else!",
"PayPhoneOccupantSwitched": "A different voice is now on the line",
"PayPhoneGiven": "You gave the phone to {1}",
"PayPhoneReceived": "{1} gave you the phone",
"PayPhoneUnableToCallPlayer": "You can't call {1} at this time. Please try again later.",
"ActionTips": {
"VehicleEngineOffWhenEnteringKey": "Use {1} to turn on or off a vehicle's engine",
"VehicleLockedAfterEntryAttempt": "Use {1} to lock or unlock a vehicle",
"ShowItemsAfterPurchase": "Use {1} to see your inventory",
"BuyCommandAfterEnterBusiness": "Use {1} to buy items from a business",
"UseItemKeyAfterEquipping": "Use {1} to use your equipped item",
"UseItemKeyAfterEquippingWalkieTalkie": "Use {1} to turn on or off your radio",
"RadioCommandAfterEnablingWalkieTalkie": "Use {1} to talk on your radio",
"ReplyToDirectMessage": "Use {1} to easily reply to a private message",
"UseItemKeyAmmoAfterEquippingWeapon": "Use {1} to load an ammo item into your equipped weapon",
"AnimationStop": "Use {1} to stop your animation",
"JobEquipmentInventory": "The job equipment is in your inventory. Use {1} to see them.",
"ViewInventory": "Use {1} to see your items",
"VehicleRepairItemUsage": "Stand next to a vehicle and use {1} to repair it",
"VehicleColourItemUsage": "Stand next to a vehicle and use {1} to change it's colour",
"VehiclePartItemUsage": "Stand next to a vehicle and use {1} to upgrade with {2}",
"AmmoClipItemUsage": "Equip the weapon and use {1} to load ammo into it",
"GenericItemUsage": "Use {1} to use the {2}",
"EnterJobVehicleForRoute": "Enter a job vehicle nearby to start a job route",
"JobLocations": "Visit a job location to get a job. Use {1} to find a job location",
"JobRouteStart": "Use {1} to start a job route with this vehicle",
"PayPhoneFirstUse": "Use {1} to end the call, and {2} to give the phone to somebody nearby"
},
"NoBusinessesWithinRange": "There are no businesses within {1} meters",
"NoHousesWithinRange": "There are no houses within {1} meters",
"NoPayPhonesWithinRange": "There are no payphones within {1} meters",
"HeaderBusinessesInRangeList": "Businesses (within {1} meters)",
"HeaderHousesInRangeList": "Businesses (within {1} meters)",
"HeaderPayPhonesInRangeList": "Businesses (within {1} meters)",
"HeaderCommandsForStaffFlagList": "Admin Commands ({1})",
"PlayerLocateDistanceAndDirection": "{1} is {2} meters {3}",
"MustBeNumber": "You need to use a number!",
"HeaderJobRoutesList": "Job Routes ({1})",
"HeaderJobRouteInfo": "Job Route Information (${1})",
"InvalidJobRoute": "Job route not found!",
"PayPhoneDeleted": "The payphone was deleted",
"PayPhoneAnswer": "Use {1} to answer the payphone",
"ResetActionTipsConfirm": "Are you sure you want to reset all seen action tips?",
"ActionTipsReset": "All seen action tips have been reset.",
"NormalChatDisabled": "Normal chat is disabled by server admin. Use chat commands instead.",
"GlobalChatDisabled": "Global out-of-character chat is disabled by server admin"
}

View File

@@ -16,12 +16,9 @@
"InvalidAnimationDistance": "The distance must be between 0 and 3",
"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",
@@ -652,28 +649,6 @@
"LeftWrist": "Left Wrist",
"RightWrist": "Right Wrist"
},
"ActionTips": {
"VehicleEngineOffWhenEnteringKey": "Use {1} to turn on or off a vehicle's engine",
"VehicleLockedAfterEntryAttempt": "Use {1} to lock or unlock a vehicle",
"ShowItemsAfterPurchase": "Use {1} to see your inventory",
"BuyCommandAfterEnterBusiness": "Use {1} to buy items from a business",
"UseItemKeyAfterEquipping": "Use {1} to use your equipped item",
"UseItemKeyAfterEquippingWalkieTalkie": "Use {1} to turn on or off your radio",
"RadioCommandAfterEnablingWalkieTalkie": "Use {1} to talk on your radio",
"ReplyToDirectMessage": "Use {1} to easily reply to a private message",
"UseItemKeyAmmoAfterEquippingWeapon": "Use {1} to load an ammo item into your equipped weapon",
"AnimationStop": "Use {1} to stop your animation",
"JobEquipmentInventory": "The job equipment is in your inventory. Use {1} to see them.",
"ViewInventory": "Use {1} to see your items",
"VehicleRepairItemUsage": "Stand next to a vehicle and use {1} to repair it",
"VehicleColourItemUsage": "Stand next to a vehicle and use {1} to change it's colour",
"VehiclePartItemUsage": "Stand next to a vehicle and use {1} to upgrade with {2}",
"AmmoClipItemUsage": "Equip the weapon and use {1} to load ammo into it",
"GenericItemUsage": "Use {1} to use the {2}",
"EnterJobVehicleForRoute": "Enter a job vehicle nearby to start a job route",
"JobLocations": "Visit a job location to get a job. Use {1} to find a job location",
"JobRouteStart": "Use {1} to start a job route with this vehicle"
},
"DisconnectReasons": {
"Unknown": "Unknown",
"LostConnection": "Lost Connection",
@@ -749,5 +724,60 @@
"Cancel": "Cancel",
"AlreadyOwnVehicle": "You already own this vehicle!",
"PropertyEntranceFeeLabel": "Entrance Fee: {1}",
"NeedToBeInJobVehicle": "You need to be in a job vehicle!"
"NeedToBeInJobVehicle": "You need to be in a job vehicle!",
"InvalidJobRank": "Job rank not found!",
"PayPhoneRecipientAnswered": "Somebody answered the call. Use normal chat to talk to them.",
"PayPhoneAnswered": "You answered the phone. Use normal chat to talk to the caller.",
"PayPhoneRecipientHangup": "The line was disconnected. You have been charged {1}",
"PayPhoneHangup": "You hung up the phone.",
"AlreadyUsingPayPhone": "You are already using a payphone!",
"NotUsingPayPhone": "You are not using a payphone!",
"NoPayPhoneCloseEnough": "There is no payphone close enough!",
"PayPhoneNotRinging": "This payphone is not ringing!",
"PayPhoneOccupied": "This payphone is already being used by someone else!",
"PayPhoneOccupantSwitched": "A different voice is now on the line",
"PayPhoneGiven": "You gave the phone to {1}",
"PayPhoneReceived": "{1} gave you the phone",
"PayPhoneUnableToCallPlayer": "You can't call {1} at this time. Please try again later.",
"ActionTips": {
"VehicleEngineOffWhenEnteringKey": "Use {1} to turn on or off a vehicle's engine",
"VehicleLockedAfterEntryAttempt": "Use {1} to lock or unlock a vehicle",
"ShowItemsAfterPurchase": "Use {1} to see your inventory",
"BuyCommandAfterEnterBusiness": "Use {1} to buy items from a business",
"UseItemKeyAfterEquipping": "Use {1} to use your equipped item",
"UseItemKeyAfterEquippingWalkieTalkie": "Use {1} to turn on or off your radio",
"RadioCommandAfterEnablingWalkieTalkie": "Use {1} to talk on your radio",
"ReplyToDirectMessage": "Use {1} to easily reply to a private message",
"UseItemKeyAmmoAfterEquippingWeapon": "Use {1} to load an ammo item into your equipped weapon",
"AnimationStop": "Use {1} to stop your animation",
"JobEquipmentInventory": "The job equipment is in your inventory. Use {1} to see them.",
"ViewInventory": "Use {1} to see your items",
"VehicleRepairItemUsage": "Stand next to a vehicle and use {1} to repair it",
"VehicleColourItemUsage": "Stand next to a vehicle and use {1} to change it's colour",
"VehiclePartItemUsage": "Stand next to a vehicle and use {1} to upgrade with {2}",
"AmmoClipItemUsage": "Equip the weapon and use {1} to load ammo into it",
"GenericItemUsage": "Use {1} to use the {2}",
"EnterJobVehicleForRoute": "Enter a job vehicle nearby to start a job route",
"JobLocations": "Visit a job location to get a job. Use {1} to find a job location",
"JobRouteStart": "Use {1} to start a job route with this vehicle",
"PayPhoneFirstUse": "Use {1} to end the call, and {2} to give the phone to somebody nearby"
},
"NoBusinessesWithinRange": "There are no businesses within {1} meters",
"NoHousesWithinRange": "There are no houses within {1} meters",
"NoPayPhonesWithinRange": "There are no payphones within {1} meters",
"HeaderBusinessesInRangeList": "Businesses (within {1} meters)",
"HeaderHousesInRangeList": "Businesses (within {1} meters)",
"HeaderPayPhonesInRangeList": "Businesses (within {1} meters)",
"HeaderCommandsForStaffFlagList": "Admin Commands ({1})",
"PlayerLocateDistanceAndDirection": "{1} is {2} meters {3}",
"MustBeNumber": "You need to use a number!",
"HeaderJobRoutesList": "Job Routes ({1})",
"HeaderJobRouteInfo": "Job Route Information (${1})",
"InvalidJobRoute": "Job route not found!",
"PayPhoneDeleted": "The payphone was deleted",
"PayPhoneAnswer": "Use {1} to answer the payphone",
"ResetActionTipsConfirm": "Are you sure you want to reset all seen action tips?",
"ActionTipsReset": "All seen action tips have been reset.",
"NormalChatDisabled": "Normal chat is disabled by server admin. Use chat commands instead.",
"GlobalChatDisabled": "Global out-of-character chat is disabled by server admin"
}

View File

@@ -15,12 +15,9 @@
"AnimationInvalidDistance": "Dystans musi być między 0 i 3",
"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",
@@ -650,28 +647,6 @@
"LeftWrist": "Lewy Nadgarstek",
"RightWrist": "Prawy Nadgarstek"
},
"ActionTips": {
"VehicleEngineOffWhenEnteringKey": "Użyj {1} aby włączyć/wyłączyć silnik pojazdu",
"VehicleLockedAfterEntryAttempt": "Użyj {1} aby otworzyć/zamknąć pojazd",
"ShowItemsAfterPurchase": "Użyj {1} aby zobaczyć swoje inventory",
"BuyCommandAfterEnterBusiness": "Użyj {1} aby kupić przedmioty od biznesu",
"UseItemKeyAfterEquipping": "Użyj {1} aby użyć wyjęty przedmiot",
"UseItemKeyAfterEquippingWalkieTalkie": "Użyj {1} aby włączyć/wyłączyć radio",
"RadioCommandAfterEnablingWalkieTalkie": "Użyj {1} aby użyć radia",
"ReplyToDirectMessage": "Użyj {1} aby odpowiedzieć na prywatną wiadomość",
"UseItemKeyAmmoAfterEquippingWeapon": "Użyj {1} aby załadować amunicje do wyjętej broni",
"AnimationStop": "Użyj {1} aby zatrzymać swoją animacje",
"JobEquipmentInventory": "Sprzęt do pracy jest w twoim inventory. Użyj {1} aby go zobaczyć.",
"ViewInventory": "Użyj {1} aby zobaczyć swoje przedmioty",
"VehicleRepairItemUsage": "Stań obok pojazdu i użyj {1} aby go naprawić",
"VehicleColourItemUsage": "Stań obok pojazdu i użyj {1} aby zmienić jego kolor",
"VehiclePartItemUsage": "Stań obok pojazdu i użyj {1} aby ulepszyć go z {2}",
"AmmoClipItemUsage": "Wyjmnij broń i użyj {1} aby załadować amunicje",
"GenericItemUsage": "Użyj {1} aby użyć {2}",
"EnterJobVehicleForRoute": "Wejdź do pobliskiego pojazdu służbowego aby rozpocząć trasę",
"JobLocations": "Odwiedź zakład pracy aby zdobyć pracę. Użyj {1} aby znaleźć zakład pracy",
"JobRouteStart": "Użyj {1} aby rozpocząć trasę z tym pojazdem"
},
"DisconnectReasons": {
"Unknown": "Nieznane",
"LostConnection": "Stracono Połączenie",
@@ -747,5 +722,60 @@
"Cancel": "Anuluj",
"AlreadyOwnVehicle": "Już posiadasz ten pojazd!",
"PropertyEntranceFeeLabel": "Opłata wejściowa: {1}",
"NeedToBeInJobVehicle": "Musisz być w firmowym pojeździe!"
"NeedToBeInJobVehicle": "Musisz być w firmowym pojeździe!",
"InvalidJobRank": "Job rank not found!",
"PayPhoneRecipientAnswered": "Somebody answered the call. Use normal chat to talk to them.",
"PayPhoneAnswered": "You answered the phone. Use normal chat to talk to the caller.",
"PayPhoneRecipientHangup": "The line was disconnected. You have been charged {1}",
"PayPhoneHangup": "You hung up the phone.",
"AlreadyUsingPayPhone": "You are already using a payphone!",
"NotUsingPayPhone": "You are not using a payphone!",
"NoPayPhoneCloseEnough": "There is no payphone close enough!",
"PayPhoneNotRinging": "This payphone is not ringing!",
"PayPhoneOccupied": "This payphone is already being used by someone else!",
"PayPhoneOccupantSwitched": "A different voice is now on the line",
"PayPhoneGiven": "You gave the phone to {1}",
"PayPhoneReceived": "{1} gave you the phone",
"PayPhoneUnableToCallPlayer": "You can't call {1} at this time. Please try again later.",
"ActionTips": {
"VehicleEngineOffWhenEnteringKey": "Użyj {1} aby włączyć/wyłączyć silnik pojazdu",
"VehicleLockedAfterEntryAttempt": "Użyj {1} aby otworzyć/zamknąć pojazd",
"ShowItemsAfterPurchase": "Użyj {1} aby zobaczyć swoje inventory",
"BuyCommandAfterEnterBusiness": "Użyj {1} aby kupić przedmioty od biznesu",
"UseItemKeyAfterEquipping": "Użyj {1} aby użyć wyjęty przedmiot",
"UseItemKeyAfterEquippingWalkieTalkie": "Użyj {1} aby włączyć/wyłączyć radio",
"RadioCommandAfterEnablingWalkieTalkie": "Użyj {1} aby użyć radia",
"ReplyToDirectMessage": "Użyj {1} aby odpowiedzieć na prywatną wiadomość",
"UseItemKeyAmmoAfterEquippingWeapon": "Użyj {1} aby załadować amunicje do wyjętej broni",
"AnimationStop": "Użyj {1} aby zatrzymać swoją animacje",
"JobEquipmentInventory": "Sprzęt do pracy jest w twoim inventory. Użyj {1} aby go zobaczyć.",
"ViewInventory": "Użyj {1} aby zobaczyć swoje przedmioty",
"VehicleRepairItemUsage": "Stań obok pojazdu i użyj {1} aby go naprawić",
"VehicleColourItemUsage": "Stań obok pojazdu i użyj {1} aby zmienić jego kolor",
"VehiclePartItemUsage": "Stań obok pojazdu i użyj {1} aby ulepszyć go z {2}",
"AmmoClipItemUsage": "Wyjmnij broń i użyj {1} aby załadować amunicje",
"GenericItemUsage": "Użyj {1} aby użyć {2}",
"EnterJobVehicleForRoute": "Wejdź do pobliskiego pojazdu służbowego aby rozpocząć trasę",
"JobLocations": "Odwiedź zakład pracy aby zdobyć pracę. Użyj {1} aby znaleźć zakład pracy",
"JobRouteStart": "Użyj {1} aby rozpocząć trasę z tym pojazdem",
"PayPhoneFirstUse": "Use {1} to end the call, and {2} to give the phone to somebody nearby"
},
"NoBusinessesWithinRange": "There are no businesses within {1} meters",
"NoHousesWithinRange": "There are no houses within {1} meters",
"NoPayPhonesWithinRange": "There are no payphones within {1} meters",
"HeaderBusinessesInRangeList": "Businesses (within {1} meters)",
"HeaderHousesInRangeList": "Businesses (within {1} meters)",
"HeaderPayPhonesInRangeList": "Businesses (within {1} meters)",
"HeaderCommandsForStaffFlagList": "Admin Commands ({1})",
"PlayerLocateDistanceAndDirection": "{1} is {2} meters {3}",
"MustBeNumber": "You need to use a number!",
"HeaderJobRoutesList": "Job Routes ({1})",
"HeaderJobRouteInfo": "Job Route Information (${1})",
"InvalidJobRoute": "Job route not found!",
"PayPhoneDeleted": "The payphone was deleted",
"PayPhoneAnswer": "Use {1} to answer the payphone",
"ResetActionTipsConfirm": "Are you sure you want to reset all seen action tips?",
"ActionTipsReset": "All seen action tips have been reset.",
"NormalChatDisabled": "Normal chat is disabled by server admin. Use chat commands instead.",
"GlobalChatDisabled": "Global out-of-character chat is disabled by server admin"
}

View File

@@ -16,12 +16,9 @@
"InvalidAnimationDistance": "Дистанция должна быть между 0 и 3",
"CantBanClient": "Вы не можете забанить этого игрока",
"PlayerAccountBanned": "Аккаунт {1} был заблокирован ",
"ClanNotFound": "Не удалось найти клан",
"ClanNameTaken": "Клан с таким именем уже существует",
"PlayerNotFound": "Не удалось найти игрока",
"ClanCantRemoveRanks": "Вы не можете убрать ранги клана",
"ClanCantAddRanks": "Вы не можете добавить новые ранги клана",
"ClanRankNotFound": "Не удалось найти ранг клана",
"ClanCantChangeMemberTag": "Вы не можете изменить теги членов клана",
"ClanPlayerNotInSameClan": "Игрок не в вашем клане",
"ClanCantChangeRankLevel": "Вы не можете изменить уровень ранга клана",
@@ -651,28 +648,6 @@
"LeftWrist": "Left Wrist",
"RightWrist": "Right Wrist"
},
"ActionTips": {
"VehicleEngineOffWhenEnteringKey": "Use {1} to turn on or off a vehicle's engine",
"VehicleLockedAfterEntryAttempt": "Use {1} to lock or unlock a vehicle",
"ShowItemsAfterPurchase": "Use {1} to see your inventory",
"BuyCommandAfterEnterBusiness": "Use {1} to buy items from a business",
"UseItemKeyAfterEquipping": "Use {1} to use your equipped item",
"UseItemKeyAfterEquippingWalkieTalkie": "Use {1} to turn on or off your radio",
"RadioCommandAfterEnablingWalkieTalkie": "Use {1} to talk on your radio",
"ReplyToDirectMessage": "Use {1} to easily reply to a private message",
"UseItemKeyAmmoAfterEquippingWeapon": "Use {1} to load an ammo item into your equipped weapon",
"AnimationStop": "Use {1} to stop your animation",
"JobEquipmentInventory": "The job equipment is in your inventory. Use {1} to see them.",
"ViewInventory": "Use {1} to see your items",
"VehicleRepairItemUsage": "Stand next to a vehicle and use {1} to repair it",
"VehicleColourItemUsage": "Stand next to a vehicle and use {1} to change it's colour",
"VehiclePartItemUsage": "Stand next to a vehicle and use {1} to upgrade with {2}",
"AmmoClipItemUsage": "Equip the weapon and use {1} to load ammo into it",
"GenericItemUsage": "Use {1} to use the {2}",
"EnterJobVehicleForRoute": "Enter a job vehicle nearby to start a job route",
"JobLocations": "Visit a job location to get a job. Use {1} to find a job location",
"JobRouteStart": "Use {1} to start a job route with this vehicle"
},
"DisconnectReasons": {
"Unknown": "Unknown",
"LostConnection": "Lost Connection",
@@ -748,5 +723,60 @@
"Cancel": "Cancel",
"AlreadyOwnVehicle": "You already own this vehicle!",
"PropertyEntranceFeeLabel": "Entrance Fee: {1}",
"NeedToBeInJobVehicle": "You need to be in a job vehicle!"
"NeedToBeInJobVehicle": "You need to be in a job vehicle!",
"InvalidJobRank": "Job rank not found!",
"PayPhoneRecipientAnswered": "Somebody answered the call. Use normal chat to talk to them.",
"PayPhoneAnswered": "You answered the phone. Use normal chat to talk to the caller.",
"PayPhoneRecipientHangup": "The line was disconnected. You have been charged {1}",
"PayPhoneHangup": "You hung up the phone.",
"AlreadyUsingPayPhone": "You are already using a payphone!",
"NotUsingPayPhone": "You are not using a payphone!",
"NoPayPhoneCloseEnough": "There is no payphone close enough!",
"PayPhoneNotRinging": "This payphone is not ringing!",
"PayPhoneOccupied": "This payphone is already being used by someone else!",
"PayPhoneOccupantSwitched": "A different voice is now on the line",
"PayPhoneGiven": "You gave the phone to {1}",
"PayPhoneReceived": "{1} gave you the phone",
"PayPhoneUnableToCallPlayer": "You can't call {1} at this time. Please try again later.",
"ActionTips": {
"VehicleEngineOffWhenEnteringKey": "Use {1} to turn on or off a vehicle's engine",
"VehicleLockedAfterEntryAttempt": "Use {1} to lock or unlock a vehicle",
"ShowItemsAfterPurchase": "Use {1} to see your inventory",
"BuyCommandAfterEnterBusiness": "Use {1} to buy items from a business",
"UseItemKeyAfterEquipping": "Use {1} to use your equipped item",
"UseItemKeyAfterEquippingWalkieTalkie": "Use {1} to turn on or off your radio",
"RadioCommandAfterEnablingWalkieTalkie": "Use {1} to talk on your radio",
"ReplyToDirectMessage": "Use {1} to easily reply to a private message",
"UseItemKeyAmmoAfterEquippingWeapon": "Use {1} to load an ammo item into your equipped weapon",
"AnimationStop": "Use {1} to stop your animation",
"JobEquipmentInventory": "The job equipment is in your inventory. Use {1} to see them.",
"ViewInventory": "Use {1} to see your items",
"VehicleRepairItemUsage": "Stand next to a vehicle and use {1} to repair it",
"VehicleColourItemUsage": "Stand next to a vehicle and use {1} to change it's colour",
"VehiclePartItemUsage": "Stand next to a vehicle and use {1} to upgrade with {2}",
"AmmoClipItemUsage": "Equip the weapon and use {1} to load ammo into it",
"GenericItemUsage": "Use {1} to use the {2}",
"EnterJobVehicleForRoute": "Enter a job vehicle nearby to start a job route",
"JobLocations": "Visit a job location to get a job. Use {1} to find a job location",
"JobRouteStart": "Use {1} to start a job route with this vehicle",
"PayPhoneFirstUse": "Use {1} to end the call, and {2} to give the phone to somebody nearby"
},
"NoBusinessesWithinRange": "There are no businesses within {1} meters",
"NoHousesWithinRange": "There are no houses within {1} meters",
"NoPayPhonesWithinRange": "There are no payphones within {1} meters",
"HeaderBusinessesInRangeList": "Businesses (within {1} meters)",
"HeaderHousesInRangeList": "Businesses (within {1} meters)",
"HeaderPayPhonesInRangeList": "Businesses (within {1} meters)",
"HeaderCommandsForStaffFlagList": "Admin Commands ({1})",
"PlayerLocateDistanceAndDirection": "{1} is {2} meters {3}",
"MustBeNumber": "You need to use a number!",
"HeaderJobRoutesList": "Job Routes ({1})",
"HeaderJobRouteInfo": "Job Route Information (${1})",
"InvalidJobRoute": "Job route not found!",
"PayPhoneDeleted": "The payphone was deleted",
"PayPhoneAnswer": "Use {1} to answer the payphone",
"ResetActionTipsConfirm": "Are you sure you want to reset all seen action tips?",
"ActionTipsReset": "All seen action tips have been reset.",
"NormalChatDisabled": "Normal chat is disabled by server admin. Use chat commands instead.",
"GlobalChatDisabled": "Global out-of-character chat is disabled by server admin"
}

View File

@@ -16,12 +16,9 @@
"InvalidAnimationDistance": "The distance must be between 0 and 3",
"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",
@@ -651,28 +648,6 @@
"LeftWrist": "Left Wrist",
"RightWrist": "Right Wrist"
},
"ActionTips": {
"VehicleEngineOffWhenEnteringKey": "Use {1} to turn on or off a vehicle's engine",
"VehicleLockedAfterEntryAttempt": "Use {1} to lock or unlock a vehicle",
"ShowItemsAfterPurchase": "Use {1} to see your inventory",
"BuyCommandAfterEnterBusiness": "Use {1} to buy items from a business",
"UseItemKeyAfterEquipping": "Use {1} to use your equipped item",
"UseItemKeyAfterEquippingWalkieTalkie": "Use {1} to turn on or off your radio",
"RadioCommandAfterEnablingWalkieTalkie": "Use {1} to talk on your radio",
"ReplyToDirectMessage": "Use {1} to easily reply to a private message",
"UseItemKeyAmmoAfterEquippingWeapon": "Use {1} to load an ammo item into your equipped weapon",
"AnimationStop": "Use {1} to stop your animation",
"JobEquipmentInventory": "The job equipment is in your inventory. Use {1} to see them.",
"ViewInventory": "Use {1} to see your items",
"VehicleRepairItemUsage": "Stand next to a vehicle and use {1} to repair it",
"VehicleColourItemUsage": "Stand next to a vehicle and use {1} to change it's colour",
"VehiclePartItemUsage": "Stand next to a vehicle and use {1} to upgrade with {2}",
"AmmoClipItemUsage": "Equip the weapon and use {1} to load ammo into it",
"GenericItemUsage": "Use {1} to use the {2}",
"EnterJobVehicleForRoute": "Enter a job vehicle nearby to start a job route",
"JobLocations": "Visit a job location to get a job. Use {1} to find a job location",
"JobRouteStart": "Use {1} to start a job route with this vehicle"
},
"DisconnectReasons": {
"Unknown": "Unknown",
"LostConnection": "Lost Connection",
@@ -748,5 +723,60 @@
"Cancel": "Cancel",
"AlreadyOwnVehicle": "You already own this vehicle!",
"PropertyEntranceFeeLabel": "Entrance Fee: {1}",
"NeedToBeInJobVehicle": "You need to be in a job vehicle!"
"NeedToBeInJobVehicle": "You need to be in a job vehicle!",
"InvalidJobRank": "Job rank not found!",
"PayPhoneRecipientAnswered": "Somebody answered the call. Use normal chat to talk to them.",
"PayPhoneAnswered": "You answered the phone. Use normal chat to talk to the caller.",
"PayPhoneRecipientHangup": "The line was disconnected. You have been charged {1}",
"PayPhoneHangup": "You hung up the phone.",
"AlreadyUsingPayPhone": "You are already using a payphone!",
"NotUsingPayPhone": "You are not using a payphone!",
"NoPayPhoneCloseEnough": "There is no payphone close enough!",
"PayPhoneNotRinging": "This payphone is not ringing!",
"PayPhoneOccupied": "This payphone is already being used by someone else!",
"PayPhoneOccupantSwitched": "A different voice is now on the line",
"PayPhoneGiven": "You gave the phone to {1}",
"PayPhoneReceived": "{1} gave you the phone",
"PayPhoneUnableToCallPlayer": "You can't call {1} at this time. Please try again later.",
"ActionTips": {
"VehicleEngineOffWhenEnteringKey": "Use {1} to turn on or off a vehicle's engine",
"VehicleLockedAfterEntryAttempt": "Use {1} to lock or unlock a vehicle",
"ShowItemsAfterPurchase": "Use {1} to see your inventory",
"BuyCommandAfterEnterBusiness": "Use {1} to buy items from a business",
"UseItemKeyAfterEquipping": "Use {1} to use your equipped item",
"UseItemKeyAfterEquippingWalkieTalkie": "Use {1} to turn on or off your radio",
"RadioCommandAfterEnablingWalkieTalkie": "Use {1} to talk on your radio",
"ReplyToDirectMessage": "Use {1} to easily reply to a private message",
"UseItemKeyAmmoAfterEquippingWeapon": "Use {1} to load an ammo item into your equipped weapon",
"AnimationStop": "Use {1} to stop your animation",
"JobEquipmentInventory": "The job equipment is in your inventory. Use {1} to see them.",
"ViewInventory": "Use {1} to see your items",
"VehicleRepairItemUsage": "Stand next to a vehicle and use {1} to repair it",
"VehicleColourItemUsage": "Stand next to a vehicle and use {1} to change it's colour",
"VehiclePartItemUsage": "Stand next to a vehicle and use {1} to upgrade with {2}",
"AmmoClipItemUsage": "Equip the weapon and use {1} to load ammo into it",
"GenericItemUsage": "Use {1} to use the {2}",
"EnterJobVehicleForRoute": "Enter a job vehicle nearby to start a job route",
"JobLocations": "Visit a job location to get a job. Use {1} to find a job location",
"JobRouteStart": "Use {1} to start a job route with this vehicle",
"PayPhoneFirstUse": "Use {1} to end the call, and {2} to give the phone to somebody nearby"
},
"NoBusinessesWithinRange": "There are no businesses within {1} meters",
"NoHousesWithinRange": "There are no houses within {1} meters",
"NoPayPhonesWithinRange": "There are no payphones within {1} meters",
"HeaderBusinessesInRangeList": "Businesses (within {1} meters)",
"HeaderHousesInRangeList": "Businesses (within {1} meters)",
"HeaderPayPhonesInRangeList": "Businesses (within {1} meters)",
"HeaderCommandsForStaffFlagList": "Admin Commands ({1})",
"PlayerLocateDistanceAndDirection": "{1} is {2} meters {3}",
"MustBeNumber": "You need to use a number!",
"HeaderJobRoutesList": "Job Routes ({1})",
"HeaderJobRouteInfo": "Job Route Information (${1})",
"InvalidJobRoute": "Job route not found!",
"PayPhoneDeleted": "The payphone was deleted",
"PayPhoneAnswer": "Use {1} to answer the payphone",
"ResetActionTipsConfirm": "Are you sure you want to reset all seen action tips?",
"ActionTipsReset": "All seen action tips have been reset.",
"NormalChatDisabled": "Normal chat is disabled by server admin. Use chat commands instead.",
"GlobalChatDisabled": "Global out-of-character chat is disabled by server admin"
}

View File

@@ -22,12 +22,9 @@
"InvalidAnimationDistance": "La distancia debe ser un numero entre el 0 y el 3",
"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",
@@ -657,28 +654,6 @@
"LeftWrist": "Left Wrist",
"RightWrist": "Right Wrist"
},
"ActionTips": {
"VehicleEngineOffWhenEnteringKey": "Use {1} to turn on or off a vehicle's engine",
"VehicleLockedAfterEntryAttempt": "Use {1} to lock or unlock a vehicle",
"ShowItemsAfterPurchase": "Use {1} to see your inventory",
"BuyCommandAfterEnterBusiness": "Use {1} to buy items from a business",
"UseItemKeyAfterEquipping": "Use {1} to use your equipped item",
"UseItemKeyAfterEquippingWalkieTalkie": "Use {1} to turn on or off your radio",
"RadioCommandAfterEnablingWalkieTalkie": "Use {1} to talk on your radio",
"ReplyToDirectMessage": "Use {1} to easily reply to a private message",
"UseItemKeyAmmoAfterEquippingWeapon": "Use {1} to load an ammo item into your equipped weapon",
"AnimationStop": "Use {1} to stop your animation",
"JobEquipmentInventory": "The job equipment is in your inventory. Use {1} to see them.",
"ViewInventory": "Use {1} to see your items",
"VehicleRepairItemUsage": "Stand next to a vehicle and use {1} to repair it",
"VehicleColourItemUsage": "Stand next to a vehicle and use {1} to change it's colour",
"VehiclePartItemUsage": "Stand next to a vehicle and use {1} to upgrade with {2}",
"AmmoClipItemUsage": "Equip the weapon and use {1} to load ammo into it",
"GenericItemUsage": "Use {1} to use the {2}",
"EnterJobVehicleForRoute": "Enter a job vehicle nearby to start a job route",
"JobLocations": "Visit a job location to get a job. Use {1} to find a job location",
"JobRouteStart": "Use {1} to start a job route with this vehicle"
},
"DisconnectReasons": {
"Unknown": "Unknown",
"LostConnection": "Lost Connection",
@@ -754,5 +729,60 @@
"Cancel": "Cancel",
"AlreadyOwnVehicle": "You already own this vehicle!",
"PropertyEntranceFeeLabel": "Entrance Fee: {1}",
"NeedToBeInJobVehicle": "You need to be in a job vehicle!"
"NeedToBeInJobVehicle": "You need to be in a job vehicle!",
"InvalidJobRank": "Job rank not found!",
"PayPhoneRecipientAnswered": "Somebody answered the call. Use normal chat to talk to them.",
"PayPhoneAnswered": "You answered the phone. Use normal chat to talk to the caller.",
"PayPhoneRecipientHangup": "The line was disconnected. You have been charged {1}",
"PayPhoneHangup": "You hung up the phone.",
"AlreadyUsingPayPhone": "You are already using a payphone!",
"NotUsingPayPhone": "You are not using a payphone!",
"NoPayPhoneCloseEnough": "There is no payphone close enough!",
"PayPhoneNotRinging": "This payphone is not ringing!",
"PayPhoneOccupied": "This payphone is already being used by someone else!",
"PayPhoneOccupantSwitched": "A different voice is now on the line",
"PayPhoneGiven": "You gave the phone to {1}",
"PayPhoneReceived": "{1} gave you the phone",
"PayPhoneUnableToCallPlayer": "You can't call {1} at this time. Please try again later.",
"ActionTips": {
"VehicleEngineOffWhenEnteringKey": "Use {1} to turn on or off a vehicle's engine",
"VehicleLockedAfterEntryAttempt": "Use {1} to lock or unlock a vehicle",
"ShowItemsAfterPurchase": "Use {1} to see your inventory",
"BuyCommandAfterEnterBusiness": "Use {1} to buy items from a business",
"UseItemKeyAfterEquipping": "Use {1} to use your equipped item",
"UseItemKeyAfterEquippingWalkieTalkie": "Use {1} to turn on or off your radio",
"RadioCommandAfterEnablingWalkieTalkie": "Use {1} to talk on your radio",
"ReplyToDirectMessage": "Use {1} to easily reply to a private message",
"UseItemKeyAmmoAfterEquippingWeapon": "Use {1} to load an ammo item into your equipped weapon",
"AnimationStop": "Use {1} to stop your animation",
"JobEquipmentInventory": "The job equipment is in your inventory. Use {1} to see them.",
"ViewInventory": "Use {1} to see your items",
"VehicleRepairItemUsage": "Stand next to a vehicle and use {1} to repair it",
"VehicleColourItemUsage": "Stand next to a vehicle and use {1} to change it's colour",
"VehiclePartItemUsage": "Stand next to a vehicle and use {1} to upgrade with {2}",
"AmmoClipItemUsage": "Equip the weapon and use {1} to load ammo into it",
"GenericItemUsage": "Use {1} to use the {2}",
"EnterJobVehicleForRoute": "Enter a job vehicle nearby to start a job route",
"JobLocations": "Visit a job location to get a job. Use {1} to find a job location",
"JobRouteStart": "Use {1} to start a job route with this vehicle",
"PayPhoneFirstUse": "Use {1} to end the call, and {2} to give the phone to somebody nearby"
},
"NoBusinessesWithinRange": "There are no businesses within {1} meters",
"NoHousesWithinRange": "There are no houses within {1} meters",
"NoPayPhonesWithinRange": "There are no payphones within {1} meters",
"HeaderBusinessesInRangeList": "Businesses (within {1} meters)",
"HeaderHousesInRangeList": "Businesses (within {1} meters)",
"HeaderPayPhonesInRangeList": "Businesses (within {1} meters)",
"HeaderCommandsForStaffFlagList": "Admin Commands ({1})",
"PlayerLocateDistanceAndDirection": "{1} is {2} meters {3}",
"MustBeNumber": "You need to use a number!",
"HeaderJobRoutesList": "Job Routes ({1})",
"HeaderJobRouteInfo": "Job Route Information (${1})",
"InvalidJobRoute": "Job route not found!",
"PayPhoneDeleted": "The payphone was deleted",
"PayPhoneAnswer": "Use {1} to answer the payphone",
"ResetActionTipsConfirm": "Are you sure you want to reset all seen action tips?",
"ActionTipsReset": "All seen action tips have been reset.",
"NormalChatDisabled": "Normal chat is disabled by server admin. Use chat commands instead.",
"GlobalChatDisabled": "Global out-of-character chat is disabled by server admin"
}

View File

@@ -8,6 +8,8 @@
<script src="scripts/shared/utilities.js" type="client" language="javascript" />
<script src="scripts/shared/gamedata.js" type="server" language="javascript" />
<script src="scripts/shared/gamedata.js" type="client" language="javascript" />
<script src="scripts/shared/queue.js" type="server" language="javascript" />
<script src="scripts/shared/queue.js" type="client" language="javascript" />
<!-- Multiplayer Mod (Wrapped Natives) -->
<!-- The goal is to just swap only these out when I port the script to a new MP mod -->
@@ -50,6 +52,7 @@
<script src="scripts/server/npc.js" type="server" language="javascript" />
<script src="scripts/server/netevents.js" type="server" language="javascript" />
<script src="scripts/server/paintball.js" type="server" language="javascript" />
<script src="scripts/server/payphone.js" type="server" language="javascript" />
<script src="scripts/server/prompt.js" type="server" language="javascript" />
<script src="scripts/server/race.js" type="server" language="javascript" />
<script src="scripts/server/radio.js" type="server" language="javascript" />
@@ -83,16 +86,29 @@
<script src="scripts/server/item/rope.js" type="server" language="javascript" />
<script src="scripts/server/item/tazer.js" type="server" language="javascript" />
<!-- Extra Client Files -->
<!-- Fonts -->
<file type="client" src="files/fonts/roboto-regular.ttf" />
<file type="client" src="files/fonts/pricedown.ttf" />
<file type="client" src="files/fonts/aurora-bold-condensed.ttf" />
<!-- Images -->
<file type="client" src="files/images/skins/none.png" />
<!--<file type="client" src="files/images/server-logo.png" />-->
<file type="client" src="files/images/gtac-logo.png" />
<file type="client" src="files/images/mafiac-logo.png" />
<file type="client" src="files/images/cursor.png" />
<!-- 3D World Icons -->
<file type="client" src="files/images/icons/objective-icon.png" />
<file type="client" src="files/images/icons/business-icon.png" />
<file type="client" src="files/images/icons/house-icon.png" />
<file type="client" src="files/images/icons/job-icon.png" />
<!-- Sounds -->
<file type="client" src="files/sounds/payphone/old-payphone-ring.mp3" />
<file type="client" src="files/sounds/payphone/old-payphone-dial.mp3" />
<file type="client" src="files/sounds/payphone/old-payphone-pickup.mp3" />
<file type="client" src="files/sounds/payphone/old-payphone-hangup.mp3" />
<!-- GUI -->
<script src="scripts/client/gui/2fa.js" type="client" language="javascript" />
<script src="scripts/client/gui/bizmgr.js" type="client" language="javascript" />
@@ -139,10 +155,12 @@
<script src="scripts/client/mousecam.js" type="client" language="javascript" />
<script src="scripts/client/nametag.js" type="client" language="javascript" />
<script src="scripts/client/npc.js" type="client" language="javascript" />
<script src="scripts/client/payphone.js" type="client" language="javascript" />
<script src="scripts/client/radio.js" type="client" language="javascript" />
<script src="scripts/client/scoreboard.js" type="client" language="javascript" />
<script src="scripts/client/skin-select.js" type="client" language="javascript" />
<script src="scripts/client/sync.js" type="client" language="javascript" />
<script src="scripts/client/timers.js" type="client" language="javascript" />
<script src="scripts/client/utilities.js" type="client" language="javascript" />
<script src="scripts/client/vehicle.js" type="client" language="javascript" />
<script src="scripts/client/netevents.js" type="client" language="javascript" />

View File

@@ -64,12 +64,14 @@ function receiveBusinessFromServer(businessId, isDeleted, name, entrancePosition
if (businessData.buyPrice > 0) {
businessData.labelInfoType = V_PROPLABEL_INFO_BUYBIZ;
} else {
if (hasInterior && !hasItems) {
if (hasInterior) {
businessData.labelInfoType = V_PROPLABEL_INFO_ENTER;
} else if (!hasInterior && hasItems) {
businessData.labelInfoType = V_PROPLABEL_INFO_BUY;
} else {
businessData.labelInfoType = V_PROPLABEL_INFO_NONE;
if (hasItems) {
businessData.labelInfoType = V_PROPLABEL_INFO_BUY;
} else {
businessData.labelInfoType = V_PROPLABEL_INFO_NONE;
}
}
}
@@ -108,17 +110,27 @@ function receiveBusinessFromServer(businessId, isDeleted, name, entrancePosition
}
} else {
logToConsole(LOG_DEBUG, `[V.RP.Business] Business ${businessId} doesn't exist. Adding ...`);
let tempBusinessData = new BusinessData(businessId, name, entrancePosition, blipModel, pickupModel, hasInterior, hasItems);
let businessData = new BusinessData(businessId, name, entrancePosition, blipModel, pickupModel, hasInterior, locked, hasItems, entranceFee);
businessData.name = name;
businessData.entrancePosition = entrancePosition;
businessData.blipModel = blipModel;
businessData.pickupModel = pickupModel;
businessData.hasInterior = hasInterior;
businessData.buyPrice = buyPrice;
businessData.rentPrice = rentPrice;
businessData.hasItems = hasItems;
businessData.locked = locked;
businessData.entranceFee = entranceFee;
if (blipModel != -1) {
let blipId = createGameBlip(tempBusinessData.blipModel, tempBusinessData.entrancePosition, tempBusinessData.name);
let blipId = createGameBlip(businessData.blipModel, businessData.entrancePosition, businessData.name);
if (blipId != -1) {
tempBusinessData.blipId = blipId;
businessData.blipId = blipId;
}
logToConsole(LOG_DEBUG, `[V.RP.Business] Business ${businessId}'s blip has been added by the server (Model ${blipModel}, ID ${blipId})`);
} else {
logToConsole(LOG_DEBUG, `[V.RP.Business] Business ${businessId} has no blip.`);
}
getServerData().businesses.push(tempBusinessData);
getServerData().businesses.push(businessData);
setAllBusinessDataIndexes();
}
}

View File

@@ -40,4 +40,17 @@ function processCameraFadeRendering() {
}
}
// ===========================================================================
function fadeLocalCamera(state, duration, colour) {
logToConsole(LOG_DEBUG, `[V.RP.Utilities] Fading camera ${(state) ? "in" : "out"} for ${duration}ms`);
cameraFadeDuration = duration;
cameraFadeStart = sdl.ticks;
cameraFadeIn = state;
cameraFadeColour = colour;
cameraFadeAlpha = (state) ? 255 : 0;
cameraFadeEnabled = true;
}
// ===========================================================================

View File

@@ -28,10 +28,11 @@ let renderHotBar = true;
let renderItemActionDelay = true;
let renderInteriorLights = true;
let logLevel = LOG_INFO;
let logLevel = LOG_INFO | LOG_DEBUG;
let weaponDamageEnabled = {};
let weaponDamageEvent = {};
let weaponDamageMultiplier = 1.0;
let forceWeapon = 0;
let forceWeaponAmmo = 0;
@@ -89,6 +90,7 @@ let localLocaleId = 0;
* @property {Array} localeStrings
* @property {Array} localeOptions
* @property {Object} cvars
* @property {Array.<PayPhoneData>} payPhones
*/
let serverData = {
houses: [],
@@ -98,6 +100,7 @@ let serverData = {
vehicles: [],
jobs: [],
cvars: {},
payPhones: [],
};
let localPlayerMoney = 0;
@@ -106,6 +109,7 @@ let localPlayerMoneyInterval = null;
let currencyString = "${AMOUNT}";
let mapChangeWarning = false;
let mapChangeToNight = false;
let cruiseControlEnabled = false;
let cruiseControlSpeed = 0.0;

View File

@@ -47,6 +47,7 @@ function addAllEventHandlers() {
addEventHandler("OnMapLoaded", onMapLoaded);
addEventHandler("OnPedEnteringVehicle", onPedEnteredVehicle);
addEventHandler("OnPedExitingVehicle", onPedExitedVehicle);
addEventHandler("OnPedInflictDamage", onPedHit);
}
}
@@ -121,6 +122,8 @@ function onProcess(event, deltaTime) {
processVehiclePurchasing();
processVehicleBurning();
processVehicleCruiseControl();
processPayPhonesDistance();
processJobRouteLocationDistance();
//checkChatBoxAutoHide(); // Will be uncommented on 1.4.0 GTAC update
//processVehicleFires();
}
@@ -158,6 +161,8 @@ function onDrawnHUD(event) {
processInteriorLightsRendering();
processCustomHUDRendering();
processCameraFadeRendering();
processJobLocationIndicatorRendering();
processMapChangeWarning();
}
// ===========================================================================
@@ -182,6 +187,7 @@ function onPedExitedVehicle(event, ped, vehicle, seat) {
cruiseControlEnabled = false;
cruiseControlSpeed = 0.0;
/*
if (localPlayer != null) {
if (ped == localPlayer) {
if (areServerElementsSupported()) {
@@ -195,6 +201,7 @@ function onPedExitedVehicle(event, ped, vehicle, seat) {
}
}
}
*/
}
// ===========================================================================
@@ -257,6 +264,16 @@ function onPedInflictDamage(event, damagedEntity, damagerEntity, weaponId, healt
// ===========================================================================
function onPedHit(event, hitPed, vec1, vec2, vec3, hitType, damage, bodyPart) {
logToConsole(LOG_DEBUG, `[V.RP.Event] Ped ${hitPed.id} (${hitPed.name}) hit using type ${hitType}, causing ${damage} to body part ${bodyPart}`);
event.preventDefault();
if (hitPed == localPlayer) {
localPlayer.health = localPlayer.health - (damage * weaponDamageMultiplier);
}
}
// ===========================================================================
function onPedEnteredSphere(event, ped, sphere) {
if (sphere == jobRouteLocationSphere) {
enteredJobRouteSphere();

View File

@@ -8,7 +8,7 @@
// ===========================================================================
let customHUDMoneyFont = null;
let customHUDMoneyColour = toColour(200, 200, 200, 200);
let customHUDMoneyColour = toColour(255, 255, 255, 255);
let customHUDMoneySize = 22.0;
// ===========================================================================
@@ -33,6 +33,7 @@ function processCustomHUDRendering() {
let text = getCurrencyString(localPlayerMoney);
logToConsole(LOG_VERBOSE, `[V.RP.HUD]: Rendering custom HUD money (${text})...`);
customHUDMoneyFont.render(text, [game.width - 150, 20], 130, 1.0, 0.0, customHUDMoneyFont.size, customHUDMoneyColour, true, true, false, true);
//graphics.drawRectangle()
} else {
logToConsole(LOG_VERBOSE | LOG_ERROR, `[V.RP.HUD]: Rendering custom HUD money FAILED. Font object is null!`);
}

View File

@@ -7,10 +7,17 @@
// TYPE: Client (JavaScript)
// ===========================================================================
let localPlayerJobType = 0;
let localPlayerJobType = -1;
let localPlayerWorking = false;
let jobRouteLocationBlip = null;
let jobRouteLocationSphere = null;
let jobRouteLocationRadius = 5.0;
let jobRouteLocationIndicatorPosition = toVector3(0.0, 0.0, 0.0);
let jobRouteLocationIndicatorSize = toVector2(32, 32);
let jobRouteLocationIndicatorEnabled = false;
let jobRouteLocationIndicatorImagePath = "files/images/icons/objective-icon.png";
let jobRouteLocationIndicatorImage = null;
let jobBlipBlinkAmount = 0;
let jobBlipBlinkTimes = 10;
@@ -36,11 +43,25 @@ class JobData {
function initJobScript() {
logToConsole(LOG_DEBUG, "[V.RP.Job]: Initializing job script ...");
jobRouteLocationIndicatorImage = loadJobRouteLocationIndicatorImage();
logToConsole(LOG_DEBUG, "[V.RP.Job]: Job script initialized!");
}
// ===========================================================================
function loadJobRouteLocationIndicatorImage() {
let imageStream = openFile(jobRouteLocationIndicatorImagePath);
let tempImage = null;
if (imageStream != null) {
tempImage = graphics.loadPNG(imageStream);
imageStream.close();
}
return tempImage;
}
// ===========================================================================
function setLocalPlayerJobType(tempJobType) {
logToConsole(LOG_DEBUG, `[V.RP.Job] Set local player job type to ${tempJobType}`);
localPlayerJobType = tempJobType;
@@ -75,6 +96,11 @@ function showJobRouteLocation(position, colour) {
blinkJobRouteLocationBlip(10, position, colour);
jobRouteLocationBlip = game.createBlip(position, 0, 2, colour);
}
if (getGame() == V_GAME_MAFIA_ONE) {
jobRouteLocationIndicatorPosition = position;
jobRouteLocationIndicatorEnabled = true;
}
}
// ===========================================================================
@@ -116,22 +142,29 @@ function blinkJobRouteLocationBlip(times, position, colour) {
function hideJobRouteLocation() {
logToConsole(LOG_DEBUG, `[V.RP.Job] Hiding job route location`);
if (jobRouteLocationBlip != null) {
destroyElement(jobRouteLocationBlip);
jobRouteLocationBlip = null;
if (isGameFeatureSupported("blip")) {
if (jobRouteLocationBlip != null) {
destroyElement(jobRouteLocationBlip);
jobRouteLocationBlip = null;
}
if (jobRouteLocationSphere != null) {
destroyElement(jobRouteLocationSphere);
jobRouteLocationSphere = null;
}
if (jobBlipBlinkTimer != null) {
clearInterval(jobBlipBlinkTimer);
}
jobBlipBlinkAmount = 0;
jobBlipBlinkTimes = 0;
}
if (jobRouteLocationSphere != null) {
destroyElement(jobRouteLocationSphere);
jobRouteLocationSphere = null;
if (getGame() == V_GAME_MAFIA_ONE) {
jobRouteLocationIndicatorPosition = toVector3(0.0, 0.0, 0.0);
jobRouteLocationIndicatorEnabled = false;
}
if (jobBlipBlinkTimer != null) {
clearInterval(jobBlipBlinkTimer);
}
jobBlipBlinkAmount = 0;
jobBlipBlinkTimes = 0;
}
// ===========================================================================
@@ -236,4 +269,45 @@ function removeJobsFromClient() {
getServerData().jobs.splice(0);
}
// ===========================================================================
function processJobLocationIndicatorRendering() {
if (jobRouteLocationIndicatorImage == null) {
logToConsole(LOG_VERBOSE, `[V.RP.Job]: Can't render job location indicator. Image is null.`);
return false;
}
if (getGame() != V_GAME_MAFIA_ONE) {
logToConsole(LOG_VERBOSE, `[V.RP.Job]: Can't render job location indicator. Unsupported game.`);
return false;
}
if (!jobRouteLocationIndicatorEnabled) {
logToConsole(LOG_VERBOSE, `[V.RP.Job]: Can't render job location indicator. Disabled`);
return false;
}
let screenPosition = getScreenFromWorldPosition(jobRouteLocationIndicatorPosition);
screenPosition = fixOffScreenPosition(screenPosition, jobRouteLocationIndicatorSize);
graphics.drawRectangle(jobRouteLocationIndicatorImage, [screenPosition.x - (jobRouteLocationIndicatorSize.x / 2), screenPosition.y - (jobRouteLocationIndicatorSize.y / 2)], [jobRouteLocationIndicatorSize.x, jobRouteLocationIndicatorSize.y]);
}
// ===========================================================================
function processJobRouteLocationDistance() {
if (getGame() != V_GAME_MAFIA_ONE) {
return false;
}
if (jobRouteLocationIndicatorEnabled == false) {
return false;
}
if (getDistance(getLocalPlayerPosition(), jobRouteLocationIndicatorPosition) <= jobRouteLocationRadius) {
logToConsole(LOG_DEBUG, `[V.RP.Job] Reached job route location`);
hideJobRouteLocation();
tellServerPlayerArrivedAtJobRouteLocation();
}
}
// ===========================================================================

View File

@@ -13,7 +13,7 @@ let jobLabels = [];
let propertyLabelNameFont = null;
let propertyLabelLockedFont = null;
let propertyLabelHeight = (getGame() == V_GAME_MAFIA_ONE) ? 2.0 : 1.0;
let propertyLabelHeight = (getGame() == V_GAME_MAFIA_ONE) ? 1.75 : 1.0;
let propertyPickupRenderDistance = 75.0;
let propertyLabelRenderDistance = 5.0;
let propertyLabelLockedOffset = 16;
@@ -27,6 +27,20 @@ let unlockedColour = toColour(50, 205, 50, 255);
let lockedColour = toColour(205, 92, 92, 255);
let jobHelpColour = toColour(234, 198, 126, 255);
let businessWorldIconPath = "files/images/icons/business-icon.png";
let jobWorldIconPath = "files/images/icons/job-icon.png";
let houseWorldIconPath = "files/images/icons/house-icon.png";
let businessWorldIconImage = null;
let jobWorldIconImage = null;
let houseWorldIconImage = null;
let businessWorldIconSize = [64, 64];
let jobWorldIconSize = [64, 64];
let houseWorldIconSize = [64, 64];
let worldIconRenderDistance = 15.0;
let businessWorldIconRenderDistance = worldIconRenderDistance;
let houseWorldIconRenderDistance = worldIconRenderDistance;
let jobWorldIconRenderDistance = worldIconRenderDistance;
// ===========================================================================
function initLabelScript() {
@@ -35,6 +49,10 @@ function initLabelScript() {
propertyLabelLockedFont = initLabelPropertyLockedFont();
jobNameLabelFont = initLabelJobNameFont();
jobHelpLabelFont = initLabelJobHelpFont();
businessWorldIconImage = initBusinessWorldIcon();
jobWorldIconImage = initJobWorldIcon();
houseWorldIconImage = initHouseWorldIcon();
logToConsole(LOG_DEBUG, "[V.RP.Label]: Label script initialized!");
}
@@ -64,6 +82,45 @@ function initLabelJobHelpFont() {
// ===========================================================================
function initBusinessWorldIcon() {
let imageStream = openFile(businessWorldIconPath);
let tempImage = null;
if (imageStream != null) {
tempImage = graphics.loadPNG(imageStream);
imageStream.close();
}
return tempImage;
}
// ===========================================================================
function initJobWorldIcon() {
let imageStream = openFile(jobWorldIconPath);
let tempImage = null;
if (imageStream != null) {
tempImage = graphics.loadPNG(imageStream);
imageStream.close();
}
return tempImage;
}
// ===========================================================================
function initHouseWorldIcon() {
let imageStream = openFile(houseWorldIconPath);
let tempImage = null;
if (imageStream != null) {
tempImage = graphics.loadPNG(imageStream);
imageStream.close();
}
return tempImage;
}
// ===========================================================================
function renderPropertyEntranceLabel(name, position, locked, isBusiness, price, rentPrice, labelInfoType, fee) {
if (localPlayer == null) {
return false;
@@ -77,6 +134,12 @@ function renderPropertyEntranceLabel(name, position, locked, isBusiness, price,
return false;
}
if (getGame() == V_GAME_MAFIA_ONE) {
if (localPlayer.vehicle != null) {
return false;
}
}
if (getGame() == V_GAME_GTA_IV) {
if (!natives.doesViewportExist(natives.getGameViewportId())) {
logToConsole(LOG_INFO, "[V.RP.Label]: Game viewport does not exist!");
@@ -218,6 +281,12 @@ function renderPropertyExitLabel(position) {
return false;
}
if (getGame() == V_GAME_MAFIA_ONE) {
if (localPlayer.vehicle != null) {
return false;
}
}
if (getGame() == V_GAME_GTA_IV) {
if (!natives.doesViewportExist(natives.getGameViewportId())) {
logToConsole(LOG_INFO, "[V.RP.Label]: Game viewport does not exist!");
@@ -230,17 +299,12 @@ function renderPropertyExitLabel(position) {
}
}
let tempPosition = position;
tempPosition.z = tempPosition.z + propertyLabelHeight;
position = getPosAbovePos(position, propertyLabelHeight);
let screenPosition = new Vec3(0.0, 0.0, 0.0);
if (getGame() == V_GAME_GTA_IV) {
screenPosition = natives.getViewportPositionOfCoord(tempPosition, natives.getGameViewportId());
screenPosition = natives.getViewportPositionOfCoord(position, natives.getGameViewportId());
} else {
screenPosition = getScreenFromWorldPosition(tempPosition);
}
if (screenPosition.x < 0 || screenPosition.x > game.width) {
return false;
screenPosition = getScreenFromWorldPosition(position);
}
let text = "EXIT";
@@ -263,6 +327,12 @@ function renderJobLabel(name, position, jobType) {
return false;
}
if (getGame() == V_GAME_MAFIA_ONE) {
if (localPlayer.vehicle != null) {
return false;
}
}
if (getGame() == V_GAME_GTA_IV) {
if (!natives.doesViewportExist(natives.getGameViewportId())) {
logToConsole(LOG_INFO, "[V.RP.Label]: Game viewport does not exist!");
@@ -275,15 +345,16 @@ function renderJobLabel(name, position, jobType) {
}
}
let tempPosition = position;
tempPosition.z = tempPosition.z + propertyLabelHeight;
position = getPosAbovePos(position, propertyLabelHeight);
let screenPosition = new Vec3(0.0, 0.0, 0.0);
if (getGame() == V_GAME_GTA_IV) {
screenPosition = natives.getViewportPositionOfCoord(tempPosition, natives.getGameViewportId());
screenPosition = natives.getViewportPositionOfCoord(position, natives.getGameViewportId());
} else {
screenPosition = getScreenFromWorldPosition(tempPosition);
screenPosition = getScreenFromWorldPosition(position);
}
logToConsole(LOG_VERBOSE, `[V.RP.Label] World [${position.x}, ${position.y}, ${position.z}] to screen [${screenPosition.x}, ${screenPosition.y}, ${screenPosition.z}]`);
if (screenPosition.x < 0 || screenPosition.x > game.width) {
return false;
}
@@ -296,7 +367,7 @@ function renderJobLabel(name, position, jobType) {
text = getLocaleString("StartWorkLabel", "/startwork");
}
} else {
if (localPlayerJobType == 0) {
if (localPlayerJobType == -1) {
text = getLocaleString("TakeJobLabel", "/takejob");
} else {
text = getLocaleString("NotYourJobLabel", "/quitjob");
@@ -316,48 +387,69 @@ function renderJobLabel(name, position, jobType) {
// -------------------------------------------------------------------------
function processLabelRendering() {
if (getGame() == V_GAME_MAFIA_ONE) {
if (localPlayer.vehicle != null) {
return false;
}
}
if (renderLabels) {
if (!areServerElementsSupported() || getGame() == V_GAME_MAFIA_ONE || getGame() == V_GAME_GTA_IV || getGame() == V_GAME_GTA_IV_EFLC) {
if (localPlayer != null) {
getServerData().businesses.forEach((business) => {
if (getDistance(localPlayer.position, business.entrancePosition) <= propertyPickupRenderDistance) {
let distance = getDistance(localPlayer.position, business.entrancePosition);
if (distance <= propertyLabelRenderDistance) {
if (getGame() == V_GAME_GTA_IV || getGame() == V_GAME_GTA_IV_EFLC) {
natives.drawColouredCylinder(getPosBelowPos(business.entrancePosition, 1.0), 0.0, 0.0, 0, 153, 255, 255);
}
if (getDistance(localPlayer.position, business.entrancePosition) <= propertyLabelRenderDistance) {
renderPropertyEntranceLabel(business.name, business.entrancePosition, business.locked, true, business.buyPrice, business.rentPrice, business.labelInfoType, business.entranceFee);
renderPropertyEntranceLabel(business.name, business.entrancePosition, business.locked, true, business.buyPrice, business.rentPrice, business.labelInfoType, business.entranceFee);
}
if (distance <= businessWorldIconRenderDistance) {
if (getGame() == V_GAME_MAFIA_ONE && localPlayer.vehicle == null) {
renderBusinessWorldIcon(getPosAbovePos(business.entrancePosition, 1.0));
}
}
});
getServerData().houses.forEach((house) => {
if (getDistance(localPlayer.position, house.entrancePosition) <= propertyPickupRenderDistance) {
let distance = getDistance(localPlayer.position, house.entrancePosition);
if (distance <= propertyLabelRenderDistance) {
if (getGame() == V_GAME_GTA_IV || getGame() == V_GAME_GTA_IV_EFLC) {
natives.drawColouredCylinder(getPosBelowPos(house.entrancePosition, 1.0), 0.0, 0.0, 0, 200, 0, 255);
}
if (getDistance(localPlayer.position, house.entrancePosition) <= propertyLabelRenderDistance) {
renderPropertyEntranceLabel(house.description, house.entrancePosition, house.locked, true, house.buyPrice, house.rentPrice, house.labelInfoType);
renderPropertyEntranceLabel(house.description, house.entrancePosition, house.locked, true, house.buyPrice, house.rentPrice, house.labelInfoType);
}
if (distance <= houseWorldIconRenderDistance) {
if (getGame() == V_GAME_MAFIA_ONE && localPlayer.vehicle == null) {
renderHouseWorldIcon(getPosAbovePos(house.entrancePosition, 1.0));
}
}
});
getServerData().jobs.forEach((job) => {
if (getDistance(localPlayer.position, job.position) <= propertyPickupRenderDistance) {
let distance = getDistance(localPlayer.position, job.position);
if (distance <= propertyLabelRenderDistance) {
if (getGame() == V_GAME_GTA_IV || getGame() == V_GAME_GTA_IV_EFLC) {
natives.drawColouredCylinder(getPosBelowPos(job.position, 1.0), 0.0, 0.0, 255, 255, 0, 255);
}
if (getDistance(localPlayer.position, job.position) <= propertyPickupRenderDistance) {
renderJobLabel(job.name, job.position, job.jobType);
renderJobLabel(job.name, job.position, job.jobId);
}
if (distance <= jobWorldIconRenderDistance) {
if (getGame() == V_GAME_MAFIA_ONE && localPlayer.vehicle == null) {
renderJobWorldIcon(getPosAbovePos(job.position, 1.0));
}
}
});
}
}
if (areWorldLabelsSupported()) {
if (arePickupsSupported() && areWorldLabelsSupported()) {
if (localPlayer != null) {
let pickups = getElementsByType(ELEMENT_PICKUP);
for (let i in pickups) {
@@ -415,4 +507,55 @@ function processLabelRendering() {
}
}
// -------------------------------------------------------------------------
function renderJobWorldIcon(position) {
if (jobWorldIconImage == null) {
logToConsole(LOG_VERBOSE, `[V.RP.Label]: Can't render job world icon. Image is null.`);
return false;
}
if (getGame() != V_GAME_MAFIA_ONE) {
logToConsole(LOG_VERBOSE, `[V.RP.Label]: Can't render job world icon. Unsupported game.`);
return false;
}
let screenPosition = getScreenFromWorldPosition(position);
graphics.drawRectangle(jobWorldIconImage, [screenPosition.x - (jobWorldIconSize[0] / 2), screenPosition.y - (jobWorldIconSize[1] / 2)], [jobWorldIconSize[0], jobWorldIconSize[1]]);
}
// -------------------------------------------------------------------------
function renderBusinessWorldIcon(position) {
if (businessWorldIconImage == null) {
logToConsole(LOG_VERBOSE, `[V.RP.Label]: Can't render business world icon. Image is null.`);
return false;
}
if (getGame() != V_GAME_MAFIA_ONE) {
logToConsole(LOG_VERBOSE, `[V.RP.Label]: Can't render business world icon. Unsupported game.`);
return false;
}
let screenPosition = getScreenFromWorldPosition(position);
graphics.drawRectangle(businessWorldIconImage, [screenPosition.x - (businessWorldIconSize[0] / 2), screenPosition.y - (businessWorldIconSize[1] / 2)], [businessWorldIconSize[0], businessWorldIconSize[1]]);
}
// -------------------------------------------------------------------------
function renderHouseWorldIcon(position) {
if (houseWorldIconImage == null) {
logToConsole(LOG_VERBOSE, `[V.RP.Label]: Can't render house world icon. Image is null.`);
return false;
}
if (getGame() != V_GAME_MAFIA_ONE) {
logToConsole(LOG_VERBOSE, `[V.RP.Label]: Can't render house world icon. Unsupported game.`);
return false;
}
let screenPosition = getScreenFromWorldPosition(position);
graphics.drawRectangle(houseWorldIconImage, [screenPosition.x - (houseWorldIconSize[0] / 2), screenPosition.y - (houseWorldIconSize[1] / 2)], [houseWorldIconSize[0], houseWorldIconSize[1]]);
}
// -------------------------------------------------------------------------

View File

@@ -8,7 +8,7 @@
// ===========================================================================
let logoImage = null;
let logoPos = toVector2(game.width - 132, game.height - 132);
let logoPos = (getGame() == V_GAME_MAFIA_ONE) ? toVector2(80, game.height - 80) : toVector2(64, 64);
let logoSize = toVector2(128, 128);
// ===========================================================================

View File

@@ -13,6 +13,7 @@ let afkStatusFont = null;
let pingFont = null;
let nametagDistance = 50.0;
let nametagWidth = 70;
let nametagHeight = (getGame() == V_GAME_MAFIA_ONE) ? 2.0 : 0.9;
let playerNames = {};
let playerColours = {};
@@ -84,21 +85,15 @@ function drawNametag(x, y, health, armour, text, ping, alpha, distance, colour,
// -------------------------------------------
// Health Bar
if (getMultiplayerMod() == V_MPMOD_GTAC) {
if (getGame() == V_GAME_GTA_III) {
// Mickey Hamfists is ridiculously tall. Raise the nametag for him a bit
if (skin == 109) {
y -= 20;
} else {
y -= 5;
}
} else {
y -= 5;
if (getGame() == V_GAME_GTA_III) {
// Mickey Hamfists is ridiculously tall. Raise the nametag for him a bit
if (skin == 109) {
y -= 15;
}
} else {
y -= 5;
}
y -= 5;
if (health > 0.0) {
let hx = x - width / 2;
let hy = y - 10 / 2;
@@ -143,20 +138,18 @@ function drawNametag(x, y, health, armour, text, ping, alpha, distance, colour,
// ===========================================================================
function updateNametag(element) {
if (!areWorldLabelsSupported()) {
if (!isGameFeatureSupported("customNametag")) {
return false;
}
if (localPlayer != null) {
let playerPos = localPlayer.position;
let elementPos = element.position;
let playerPosition = localPlayer.position;
let elementPosition = element.position;
elementPos[2] += 0.9;
elementPosition = getPosAbovePos(elementPosition, nametagHeight);
//if(typeof element.getComponentPosition()) {
let screenPos = getScreenFromWorldPosition(elementPos);
if (screenPos[2] >= 0.0) {
let screenPosition = getScreenFromWorldPosition(elementPosition);
if (screenPosition[2] >= 0.0 || getGame() == V_GAME_MAFIA_ONE) {
let health = element.health / 100.0;
if (health > 1.0) {
health = 1.0;
@@ -167,10 +160,10 @@ function updateNametag(element) {
armour = 1.0;
}
let distance = playerPos.distance(elementPos);
let distance = playerPosition.distance(elementPosition);
if (distance <= nametagDistance) {
if (typeof game.processLineOfSight != "undefined") {
let losCheck = game.processLineOfSight(playerPos, elementPos, true, false, false, true, true, false, true, true);
let losCheck = game.processLineOfSight(playerPosition, elementPosition, true, false, false, true, true, false, true, true);
if (losCheck != null) {
return false;
}
@@ -182,25 +175,23 @@ function updateNametag(element) {
let paused = false;
let ping = -1;
if (element.isType(ELEMENT_PLAYER)) {
if (typeof playerNames[element.name] != "undefined") {
name = playerNames[element.name];
}
if (typeof playerPaused[element.name] != "undefined") {
paused = playerPaused[element.name];
}
if (typeof playerColours[element.name] != "undefined") {
colour = playerColours[element.name];
}
if (typeof playerPing[element.name] != "undefined") {
ping = playerPing[element.name];
}
if (typeof playerNames[element.name] != "undefined") {
name = playerNames[element.name];
}
drawNametag(screenPos[0], screenPos[1], health, armour, name, ping, 1.0 - distance / nametagDistance, distance, colour, paused, element.skin);
if (typeof playerPaused[element.name] != "undefined") {
paused = playerPaused[element.name];
}
if (typeof playerColours[element.name] != "undefined") {
colour = playerColours[element.name];
}
if (typeof playerPing[element.name] != "undefined") {
ping = playerPing[element.name];
}
drawNametag(screenPosition[0], screenPosition[1], health, armour, name, ping, 1.0 - distance / nametagDistance, distance, colour, paused, element.skin);
}
}
}
@@ -224,6 +215,12 @@ function processNameTagRendering(event) {
// return false;
//}
if (getGame() == V_GAME_MAFIA_ONE) {
if (localPlayer.vehicle != null) {
return false;
}
}
getElementsByType(ELEMENT_PED).forEach(function (ped) {
if (ped != localPlayer) {
updateNametag(ped);

View File

@@ -110,7 +110,7 @@ function addAllNetworkHandlers() {
addNetworkEventHandler("v.rp.changePassword", showChangePasswordGUI);
addNetworkEventHandler("v.rp.showLocaleChooser", showLocaleChooserGUI);
addNetworkEventHandler("v.rp.guiColour", setGUIColours);
addNetworkEventHandler("v.rp.mapChangeWarning", setMapChangeWarningState);
addNetworkEventHandler("v.rp.mapChangingSoon", setMapChangeWarningState);
// 2D Rendering
addNetworkEventHandler("v.rp.set2DRendering", set2DRendering);
@@ -141,6 +141,14 @@ function addAllNetworkHandlers() {
addNetworkEventHandler("v.rp.nametag", updatePlayerNameTag);
addNetworkEventHandler("v.rp.nametagDistance", setNameTagDistance);
// PayPhones
addNetworkEventHandler("v.rp.payPhone", receivePayPhoneFromServer);
addNetworkEventHandler("v.rp.payPhoneState", receivePayPhoneStateFromServer);
addNetworkEventHandler("v.rp.removePayPhones", removePayPhonesFromClient);
addNetworkEventHandler("v.rp.payPhoneDial", payPhoneDial);
addNetworkEventHandler("v.rp.payPhoneHangup", payPhoneHangup);
addNetworkEventHandler("v.rp.payPhonePickup", payPhonePickup);
// Misc
addNetworkEventHandler("v.rp.mouseCursor", toggleMouseCursor);
addNetworkEventHandler("v.rp.mouseCamera", toggleMouseCamera);
@@ -152,6 +160,7 @@ function addAllNetworkHandlers() {
addNetworkEventHandler("v.rp.minuteDuration", setMinuteDuration);
addNetworkEventHandler("v.rp.snow", setSnowState);
addNetworkEventHandler("v.rp.enterPropertyKey", setEnterPropertyKey);
addNetworkEventHandler("v.rp.scoreBoardKey", setScoreBoardKey);
addNetworkEventHandler("v.rp.skinSelect", toggleSkinSelect);
addNetworkEventHandler("v.rp.hotbar", updatePlayerHotBar);
addNetworkEventHandler("v.rp.logLevel", setLogLevel);
@@ -167,6 +176,7 @@ function addAllNetworkHandlers() {
addNetworkEventHandler("v.rp.profanityFilter", setProfanityFilterState);
addNetworkEventHandler("v.rp.currencyString", receiveCurrencyStringFromServer);
addNetworkEventHandler("v.rp.token", serverRequestedToken);
addNetworkEventHandler("v.rp.incomingDamageMultiplier", setIncomingDamageMultiplier);
}
// ===========================================================================
@@ -286,9 +296,8 @@ function setEnterPropertyKey(key) {
if (key == -1) {
enterPropertyKey = null;
} else {
enterPropertyKey = key;
enterPropertyKey = toInteger(key);
}
}
// ===========================================================================
@@ -464,8 +473,9 @@ function receiveCurrencyStringFromServer(newCurrencyString) {
// ===========================================================================
function setMapChangeWarningState(state) {
function setMapChangeWarningState(state, changeToNight) {
mapChangeWarning = state;
mapChangeToNight = changeToNight;
}
// ===========================================================================
@@ -487,4 +497,10 @@ function serverRequestedToken() {
sendNetworkEventToServer("v.rp.token", token);
}
// ===========================================================================
function setIncomingDamageMultiplier(tempMultiplier) {
weaponDamageMultiplier = tempMultiplier;
}
// ===========================================================================

252
scripts/client/payphone.js Normal file
View File

@@ -0,0 +1,252 @@
// ===========================================================================
// Vortrex's Roleplay Resource
// https://github.com/VortrexFTW/v-roleplay
// ===========================================================================
// FILE: payphone.js
// DESC: Provides payphone functions and processing
// TYPE: Client (JavaScript)
// ===========================================================================
let payPhoneMaxAudibleDistance = 75;
let payPhoneRingMaxVolume = 50;
let payPhoneRingingIndicatorImage = null;
let payPhoneRingingIndicatorImagePath = "files/images/payphone-ringing.png";
// Will be unnecessary once MafiaC has game sound playback in scripting
let payPhoneRingingSound = null;
let payPhoneDialingSound = null;
let payPhonePickupSound = null;
let payPhoneHangupSound = null;
let payPhoneRingingSoundFilePath = "files/sounds/payphone/old-payphone-ring.mp3";
let payPhoneDialingSoundFilePath = "files/sounds/payphone/old-payphone-dial.mp3";
let payPhonePickupSoundFilePath = "files/sounds/payphone/old-payphone-pickup.mp3";
let payPhoneHangupSoundFilePath = "files/sounds/payphone/old-payphone-hangup.mp3";
let ringingPayPhone = -1;
// ===========================================================================
class PayPhoneData {
constructor(payPhoneId, state, position) {
this.index = -1;
this.payPhoneId = payPhoneId;
this.position = position;
this.state = state;
}
}
// ===========================================================================
function initPayPhoneScript() {
logToConsole(LOG_DEBUG, "[V.RP.PayPhone]: Initializing payphone script ...");
//payPhoneRingingIndicatorImage = loadPayPhoneRingingIndicatorImage();
payPhoneRingingSound = loadPayPhoneRingingSound();
payPhoneDialingSound = loadPayPhoneDialingSound();
payPhonePickupSound = loadPayPhonePickupSound();
payPhoneHangupSound = loadPayPhoneHangupSound();
logToConsole(LOG_DEBUG, "[V.RP.PayPhone]: Payphone script initialized!");
}
// ===========================================================================
function loadPayPhoneRingingIndicatorImage() {
let imageStream = openFile(payPhoneRingingIndicatorImagePath);
let tempImage = null;
if (imageStream != null) {
tempImage = graphics.loadPNG(imageStream);
imageStream.close();
}
return tempImage;
}
// ===========================================================================
function loadPayPhoneRingingSound() {
let soundStream = openFile(payPhoneRingingSoundFilePath);
let tempSound = null;
if (soundStream != null) {
tempSound = audio.createSound(soundStream, true);
soundStream.close();
}
return tempSound;
}
// ===========================================================================
function loadPayPhoneDialingSound() {
let soundStream = openFile(payPhoneDialingSoundFilePath);
let tempSound = null;
if (soundStream != null) {
tempSound = audio.createSound(soundStream, false);
soundStream.close();
}
if (tempSound != null) {
tempSound.volume = 1.0;
}
return tempSound;
}
// ===========================================================================
function loadPayPhonePickupSound() {
let soundStream = openFile(payPhonePickupSoundFilePath);
let tempSound = null;
if (soundStream != null) {
tempSound = audio.createSound(soundStream, false);
soundStream.close();
}
if (tempSound != null) {
tempSound.volume = 1.0;
}
return tempSound;
}
// ===========================================================================
function loadPayPhoneHangupSound() {
let soundStream = openFile(payPhoneHangupSoundFilePath);
let tempSound = null;
if (soundStream != null) {
tempSound = audio.createSound(soundStream, false);
soundStream.close();
}
if (tempSound != null) {
tempSound.volume = 1.0;
}
return tempSound;
}
// ===========================================================================
function processPayPhonesDistance() {
let tempRingingPhone = -1;
for (let i in getServerData().payPhones) {
if (getServerData().payPhones[i].state == V_PAYPHONE_STATE_RINGING) {
if (getDistance(getLocalPlayerPosition(), getServerData().payPhones[i].position) <= payPhoneMaxAudibleDistance) {
if (tempRingingPhone != -1) {
if (getDistance(getLocalPlayerPosition(), getServerData().payPhones[i].position) <= getDistance(getLocalPlayerPosition(), getServerData().payPhones[tempRingingPhone].position)) {
tempRingingPhone = i;
}
} else {
tempRingingPhone = i;
}
}
}
}
if (tempRingingPhone == -1) {
logToConsole(LOG_VERBOSE, "[V.RP.PayPhone]: No phones are ringing, stopping all ring sounds");
payPhoneRingingSound.stop();
} else {
let distance = getDistance(getLocalPlayerPosition(), getServerData().payPhones[tempRingingPhone].position);
let distancePercent = (payPhoneRingMaxVolume - (distance * 100 / payPhoneMaxAudibleDistance));
payPhoneRingingSound.volume = distancePercent / 100;
if (ringingPayPhone == -1) {
logToConsole(LOG_VERBOSE, "[V.RP.PayPhone]: No previous phone ringing, starting ring sound");
payPhoneRingingSound.play();
}
}
ringingPayPhone = tempRingingPhone;
}
// ===========================================================================
function receivePayPhoneFromServer(payPhoneId, isDeleted, state, position) {
logToConsole(LOG_DEBUG, `[V.RP.PayPhone] Received payphone ${payPhoneId} from server`);
if (!areServerElementsSupported() || getGame() == V_GAME_MAFIA_ONE || getGame() == V_GAME_GTA_IV) {
if (isDeleted == true) {
getServerData().payPhones.splice(payPhoneId, 1);
return false;
}
if (getPayPhoneData(payPhoneId) != false) {
logToConsole(LOG_DEBUG, `[V.RP.PayPhone] Payphone ${payPhoneId} already exists. Updating ...`);
let payPhoneData = getPayPhoneData(payPhoneId);
payPhoneData.state = state;
payPhoneData.position = position;
} else {
logToConsole(LOG_DEBUG, `[V.RP.PayPhone] Payphone ${payPhoneId} doesn't exist. Adding ...`);
let tempPayPhoneData = new PayPhoneData(payPhoneId, state, position);
getServerData().payPhones.push(tempPayPhoneData);
}
}
}
// ===========================================================================
function receivePayPhoneStateFromServer(payPhoneId, state) {
logToConsole(LOG_DEBUG, `[V.RP.PayPhone] Received payphone ${payPhoneId} state (${state}) from server`);
if (payPhoneId != -1) {
if (getPayPhoneData(payPhoneId) == false) {
return false;
}
getPayPhoneData(payPhoneId).state = state;
} else {
for (let i in getServerData().payPhones) {
getServerData().payPhones[i].state = state;
}
}
}
// ===========================================================================
/**
* @param {number} payPhoneId - The ID of the payphone (initially provided by server)
* @return {PayPhoneData} The payphone's data (class instance)
*/
function getPayPhoneData(payPhoneId) {
if (payPhoneId == -1) {
return false;
}
for (let i in getServerData().payPhones) {
if (getServerData().payPhones[i].payPhoneId == payPhoneId) {
return getServerData().payPhones[i];
}
}
return false;
}
// ===========================================================================
function removePayPhonesFromClient() {
clearArray(getServerData().payPhones);
}
// ===========================================================================
function payPhoneDial() {
logToConsole(LOG_DEBUG, "[V.RP.PayPhone]: Playing payphone dial sound");
payPhoneDialingSound.play();
}
// ===========================================================================
function payPhoneHangup() {
logToConsole(LOG_DEBUG, "[V.RP.PayPhone]: Playing payphone hangup sound");
payPhoneHangupSound.play();
}
// ===========================================================================
function payPhonePickup() {
logToConsole(LOG_DEBUG, "[V.RP.PayPhone]: Playing payphone pickup sound");
payPhonePickupSound.play();
}
// ===========================================================================

View File

@@ -12,7 +12,7 @@ let scoreBoardListFont = null;
let pausedColour = COLOUR_RED;
let scoreboardKey = SDLK_TAB;
let scoreBoardKey = null;
// ===========================================================================
@@ -38,67 +38,97 @@ function initScoreBoardListFont() {
// ===========================================================================
function processScoreBoardRendering() {
if (isAnyGUIActive()) {
if (!renderScoreBoard) {
logToConsole(LOG_VERBOSE | LOG_ERROR, `[V.RP.ScoreBoard] Could not render scoreboard. Scoreboard rendering is disabled!`);
return false;
}
if (renderScoreBoard) {
if (isKeyDown(SDLK_TAB)) {
if (scoreBoardListFont != null && scoreBoardTitleFont != null) {
let scoreboardStart = (game.height / 2) - (Math.floor(getClients().length / 2) * 20);
let titleSize = scoreBoardTitleFont.measure("PLAYERS", game.width, 0.0, 1.0, 10, false, false);
scoreBoardTitleFont.render("PLAYERS", [game.width / 2, scoreboardStart - 50], 0, 0.5, 0.0, scoreBoardTitleFont.size, COLOUR_WHITE, false, false, false, true);
if (scoreBoardListFont == null) {
logToConsole(LOG_VERBOSE | LOG_ERROR, `[V.RP.ScoreBoard] Could not render scoreboard. List font is null!`);
return false;
}
titleSize = scoreBoardTitleFont.measure("____________________________", game.width, 0.0, 1.0, 10, false, false);
scoreBoardTitleFont.render("____________________________", [game.width / 2, scoreboardStart - 35], 0, 0.5, 0.0, scoreBoardTitleFont.size, COLOUR_WHITE, false, false, false, true);
if (scoreBoardTitleFont == null) {
logToConsole(LOG_VERBOSE | LOG_ERROR, `[V.RP.ScoreBoard] Could not render scoreboard. Title font is null!`);
return false;
}
let clients = getClients();
for (let i in clients) {
if (!clients[i].console) {
let name = clients[i].name;
let colour = COLOUR_WHITE;
let paused = false;
let ping = "-1";
if (isAnyGUIActive()) {
logToConsole(LOG_VERBOSE | LOG_ERROR, `[V.RP.ScoreBoard] Could not render scoreboard. A GUI window is active!`);
return false;
}
if (typeof playerNames[clients[i].name] != "undefined") {
name = playerNames[clients[i].name];
}
if (scoreBoardKey == null) {
return false;
}
if (typeof playerPaused[clients[i].name] != "undefined") {
paused = playerPaused[clients[i].name];
}
if (!isKeyDown(scoreBoardKey)) {
return false;
}
if (typeof playerColours[clients[i].name] != "undefined") {
colour = playerColours[clients[i].name];
}
let scoreboardStart = (game.height / 2) - (Math.floor(getClients().length / 2) * 20);
let titleSize = scoreBoardTitleFont.measure("PLAYERS", game.width, 0.0, 1.0, 10, false, false);
scoreBoardTitleFont.render("PLAYERS", [game.width / 2, scoreboardStart - 50], 0, 0.5, 0.0, scoreBoardTitleFont.size, COLOUR_WHITE, false, false, false, true);
if (typeof playerPing[clients[i].name] != "undefined") {
ping = toString(playerPing[clients[i].name]);
}
titleSize = scoreBoardTitleFont.measure("____________________________", game.width, 0.0, 1.0, 10, false, false);
scoreBoardTitleFont.render("____________________________", [game.width / 2, scoreboardStart - 35], 0, 0.5, 0.0, scoreBoardTitleFont.size, COLOUR_WHITE, false, false, false, true);
// Player ID
let text = String(clients[i].index);
let size = scoreBoardListFont.measure(text, 75, 0.0, 1.0, 10, false, false);
scoreBoardListFont.render(text, [game.width / 2 - 100, scoreboardStart + (i * 20)], 0, 0.5, 0.0, scoreBoardListFont.size, COLOUR_WHITE, false, false, false, true);
let clients = getClients();
for (let i in clients) {
if (!clients[i].console) {
let name = clients[i].name;
let colour = COLOUR_WHITE;
let paused = false;
let ping = "-1";
// Player Name
text = name;
size = scoreBoardListFont.measure(text, 100, 0.0, 1.0, 10, false, false);
scoreBoardListFont.render(text, [game.width / 2, scoreboardStart + (i * 20)], 0, 0.5, 0.0, scoreBoardListFont.size, colour, false, false, false, true);
if (typeof playerNames[clients[i].name] != "undefined") {
name = playerNames[clients[i].name];
}
// Ping
text = ping;
size = scoreBoardListFont.measure(ping, 75, 0.0, 1.0, 10, false, false);
scoreBoardListFont.render(ping, [game.width / 2 + 100, scoreboardStart + (i * 20)], 0, 0.5, 0.0, scoreBoardListFont.size, COLOUR_WHITE, false, false, false, true);
if (typeof playerPaused[clients[i].name] != "undefined") {
paused = playerPaused[clients[i].name];
}
// PAUSED Status (depends on resource "afk")
if (paused == true) {
size = scoreBoardListFont.measure("PAUSED", 100, 0.0, 1.0, 10, false, false);
scoreBoardListFont.render("PAUSED", [game.width / 2 + 200, scoreboardStart + (i * 20)], 0, 0.5, 0.0, scoreBoardListFont.size, pausedColour, false, false, false, true);
}
}
}
if (typeof playerColours[clients[i].name] != "undefined") {
colour = playerColours[clients[i].name];
}
if (typeof playerPing[clients[i].name] != "undefined") {
ping = toString(playerPing[clients[i].name]);
}
// Player ID
let text = String(clients[i].index);
let size = scoreBoardListFont.measure(text, 75, 0.0, 1.0, 10, false, false);
scoreBoardListFont.render(text, [game.width / 2 - 100, scoreboardStart + (i * 20)], 0, 0.5, 0.0, scoreBoardListFont.size, COLOUR_WHITE, false, false, false, true);
// Player Name
text = name;
size = scoreBoardListFont.measure(text, 100, 0.0, 1.0, 10, false, false);
scoreBoardListFont.render(text, [game.width / 2, scoreboardStart + (i * 20)], 0, 0.5, 0.0, scoreBoardListFont.size, colour, false, false, false, true);
// Ping
text = ping;
size = scoreBoardListFont.measure(ping, 75, 0.0, 1.0, 10, false, false);
scoreBoardListFont.render(ping, [game.width / 2 + 100, scoreboardStart + (i * 20)], 0, 0.5, 0.0, scoreBoardListFont.size, COLOUR_WHITE, false, false, false, true);
// PAUSED Status (depends on resource "afk")
if (paused == true) {
size = scoreBoardListFont.measure("PAUSED", 100, 0.0, 1.0, 10, false, false);
scoreBoardListFont.render("PAUSED", [game.width / 2 + 200, scoreboardStart + (i * 20)], 0, 0.5, 0.0, scoreBoardListFont.size, pausedColour, false, false, false, true);
}
}
}
}
}
// ===========================================================================
function setScoreBoardKey(key) {
if (key == -1) {
scoreBoardKey = null;
} else {
scoreBoardKey = toInteger(key);
}
}
// ===========================================================================

View File

@@ -22,8 +22,13 @@ function initClientScripts() {
initSkinSelectScript();
initCursorScript();
initCustomHUDScript();
initPayPhoneScript();
initTimersScript();
initJobScript();
addAllNetworkHandlers();
initTimers();
}
// ===========================================================================

View File

@@ -49,15 +49,9 @@ function processSync(event, deltaTime) {
// ===========================================================================
function setVehicleLights(vehicleId, state) {
//if (getGame() == V_GAME_GTA_IV) {
// if (!state) {
// natives.forceCarLights(natives.getVehicleFromNetworkId(vehicleId, 0));
// } else {
// natives.forceCarLights(natives.getVehicleFromNetworkId(vehicleId, 1));
// }
//} else {
getElementFromId(vehicleId).lights = state;
//}
if (getElementFromId(vehicleId) != null) {
getElementFromId(vehicleId).lights = state;
}
}
// ===========================================================================

20
scripts/client/timers.js Normal file
View File

@@ -0,0 +1,20 @@
// ===========================================================================
// Vortrex's Roleplay Resource
// https://github.com/VortrexFTW/v-roleplay
// ===========================================================================
// FILE: timers.js
// DESC: Provides timer functions and usage
// TYPE: Client (JavaScript)
// ===========================================================================
function initTimersScript() {
logToConsole(LOG_DEBUG, "[V.RP.Timers]: Initializing timer script ...");
logToConsole(LOG_DEBUG, "[V.RP.Timers]: Timers script initialized!");
}
// ===========================================================================
function initTimers() {
}
// ===========================================================================

View File

@@ -28,20 +28,12 @@ function setLocalPlayerControlState(controlState, cursorState = false) {
// ===========================================================================
function fadeLocalCamera(state, duration, colour) {
logToConsole(LOG_DEBUG, `[V.RP.Utilities] Fading camera ${(state) ? "in" : "out"} for ${duration}ms`);
cameraFadeDuration = duration;
cameraFadeStart = sdl.ticks;
cameraFadeIn = state;
cameraFadeColour = colour;
cameraFadeAlpha = (state) ? 255 : 0;
cameraFadeEnabled = true;
}
// ===========================================================================
function removeLocalPlayerFromVehicle() {
if (getGame() == V_GAME_MAFIA_ONE) {
localPlayer.removeFromVehicle(localPlayer.vehicle, 0);
localPlayer.position = getPosAbovePos(localPlayer.position, 5);
}
localPlayer.removeFromVehicle();
}
@@ -405,36 +397,6 @@ function processWantedLevelReset() {
// ===========================================================================
function processLocalPlayerVehicleControlState() {
if (areServerElementsSupported()) {
if (localPlayer.vehicle != null) {
if (doesEntityDataExist(localPlayer.vehicle, "v.rp.engine")) {
if (getEntityData(localPlayer.vehicle, "v.rp.engine") == false) {
if (localPlayer.vehicle.engine == true) {
localPlayer.vehicle.engine = false;
}
//localPlayer.vehicle.netFlags.sendSync = false;
if (!localPlayer.vehicle.engine) {
if (typeof localPlayer.vehicle.velocity != "undefined") {
localPlayer.vehicle.velocity = toVector3(0.0, 0.0, 0.0);
localPlayer.vehicle.turnVelocity = toVector3(0.0, 0.0, 0.0);
}
//if (parkedVehiclePosition) {
// localPlayer.vehicle.position = parkedVehiclePosition;
// localPlayer.vehicle.heading = parkedVehicleHeading;
//}
}
} else {
//localPlayer.vehicle.netFlags.sendSync = true;
}
}
}
}
}
// ===========================================================================
function forceLocalPlayerEquippedWeaponItem() {
if (typeof localPlayer.weapon != "undefined") {
if (forceWeapon != 0) {
@@ -631,4 +593,32 @@ function setLocalPlayerMoney(amount) {
updateLocalPlayerMoney();
}
// ===========================================================================
function fixOffScreenPosition(position, margin = toVector2(0.0, 0.0)) {
if (position.x <= 0) {
position.x = 0.0 + (margin.x / 2);
} else if (position.x > game.width) {
position.x = game.width - (margin.x / 2);
}
if (position.y <= 0) {
position.y = 0.0 + (margin.y / 2);
} else if (position.y > game.height) {
position.y = game.height - (margin.y / 2);
}
return position;
}
// ===========================================================================
function processMapChangeWarning() {
if (mapChangeWarning == false) {
return false;
}
smallGameMessageFonts["AuroraBdCnBT"].render(`Map is changing to ${(mapChangeToNight) ? "night" : "day"} soon!`, [0, game.height - 90], game.width, 0.5, 0.0, smallGameMessageFonts["AuroraBdCnBT"].size, getColourByName("yellow"), true, true, false, true);
}
// ===========================================================================

View File

@@ -171,4 +171,27 @@ function removeVehiclesFromClient() {
getServerData().vehicles.splice(0);
}
// ===========================================================================
function processLocalPlayerVehicleControlState() {
if (areServerElementsSupported()) {
if (localPlayer.vehicle != null) {
if (doesEntityDataExist(localPlayer.vehicle, "v.rp.engine")) {
if (getEntityData(localPlayer.vehicle, "v.rp.engine") == false) {
setImmediate(function () {
localPlayer.vehicle.engine = getEntityData(localPlayer.vehicle, "v.rp.engine");
});
if (!getEntityData(localPlayer.vehicle, "v.rp.engine")) {
if (typeof localPlayer.vehicle.velocity != "undefined") {
localPlayer.vehicle.velocity = toVector3(0.0, 0.0, 0.0);
localPlayer.vehicle.turnVelocity = toVector3(0.0, 0.0, 0.0);
}
}
}
}
}
}
}
// ===========================================================================

View File

@@ -48,6 +48,7 @@ class AccountData {
this.databaseId = 0;
this.name = "";
this.password = "";
this.passwordRevision = 0;
this.registerDate = 0;
this.flags = {
moderation: 0,
@@ -78,6 +79,7 @@ class AccountData {
this.databaseId = toInteger(dbAssoc["acct_id"]);
this.name = toString(dbAssoc["acct_name"]);
this.password = toString(dbAssoc["acct_pass"]);
this.passwordRevision = toString(dbAssoc["acct_pass_revision"]);
this.registerDate = toInteger(dbAssoc["acct_when_registered"]);
this.flags = {
moderation: toInteger(dbAssoc["acct_svr_mod_flags"]),
@@ -614,6 +616,13 @@ function verifyAccountEmailCommand(command, params, client) {
// ===========================================================================
function resetActionTipsCommand(command, params, client) {
getPlayerData(client).promptType = V_PROMPT_RESETACTIONTIPS;
showPlayerPrompt(client, getLocaleString(client, "ResetActionTipsConfirm"), getLocaleString(client, "GUIWarningTitle"), getLocaleString(client, "Yes"), getLocaleString(client, "No"));
}
// ===========================================================================
/*
function resetAccountPasswordCommand(command, params, client) {
if(areParamsEmpty(params)) {
@@ -802,7 +811,7 @@ function getAccountHashingFunction() {
// ===========================================================================
async function isNameRegistered(name) {
function isNameRegistered(name) {
let accountData = loadAccountFromName(name, true);
if (accountData.databaseId > 0) {
return true;
@@ -813,16 +822,21 @@ async function isNameRegistered(name) {
// ===========================================================================
function hashAccountPassword(name, password) {
function hashAccountPassword(name, password, revision = 0) {
let hashFunction = getAccountHashingFunction();
let saltedInfo = saltAccountInfo(name, password);
let saltedInfo = saltAccountInfo(name, password, revision);
return hashFunction(saltedInfo);
}
// ===========================================================================
function saltAccountInfo(name, password) {
return `ag.gaming.${accountSaltHash}.${name}.${password}`;
function saltAccountInfo(name, password, revision = 0) {
let tempString = getSecurityConfig().accountPasswordSaltAlgorithm[revision];
tempString = tempString.replace("{NAME}", name);
tempString = tempString.replace("{PASSWORD}", password);
tempString = tempString.replace("{SALTHASH}", getSecurityConfig().accountSaltHash[revision]);
return tempString;
}
// ===========================================================================
@@ -915,6 +929,7 @@ function saveAccountToDatabase(accountData) {
["acct_streaming_radio_volume", accountData.streamingRadioVolume],
["acct_ip", accountData.ipAddress],
["acct_locale", accountData.locale],
["acct_pass_revision", accountData.passwordRevision],
];
let data2 = [
@@ -1070,15 +1085,15 @@ function saveAccountContactsToDatabase(accountContactData) {
// ===========================================================================
function createAccount(name, password, email = "") {
function createAccount(name, password, email = "", passwordRevision = 0) {
let dbConnection = connectToDatabase();
if (dbConnection) {
let hashedPassword = hashAccountPassword(name, password);
let hashedPassword = hashAccountPassword(name, password, passwordRevision);
let safeName = escapeDatabaseString(dbConnection, name);
let safeEmail = escapeDatabaseString(dbConnection, email);
let dbQuery = queryDatabase(dbConnection, `INSERT INTO acct_main (acct_name, acct_pass, acct_email, acct_when_registered) VALUES ('${safeName}', '${hashedPassword}', '${safeEmail}', CURRENT_TIMESTAMP())`);
let dbQuery = queryDatabase(dbConnection, `INSERT INTO acct_main (acct_name, acct_pass, acct_email, acct_when_registered, acct_pass_revision) VALUES ('${safeName}', '${hashedPassword}', '${safeEmail}', UNIX_TIMESTAMP(), ${passwordRevision})`);
if (getDatabaseInsertId(dbConnection) > 0) {
let insertId = getDatabaseInsertId(dbConnection);
createDefaultAccountServerData(insertId);
@@ -1478,6 +1493,8 @@ function savePlayerToDatabase(client) {
}
}
getPlayerCurrentSubAccount(client).payDayAmount = getPlayerData(client).payDayAmount;
saveSubAccountToDatabase(getPlayerCurrentSubAccount(client));
}
logToConsole(LOG_DEBUG, `[V.RP.Account]: Saved client ${getPlayerDisplayForConsole(client)} to database successfully!`);
@@ -1732,34 +1749,34 @@ function generateEmailVerificationCode() {
// ===========================================================================
async function sendEmailVerificationEmail(client, emailVerificationCode) {
function sendEmailVerificationEmail(client, emailVerificationCode) {
let emailBodyText = getEmailConfig().bodyContent.confirmEmail;
emailBodyText = emailBodyText.replace("{VERIFICATIONCODE}", emailVerificationCode);
emailBodyText = emailBodyText.replace("{SERVERNAME}", getServerName());
await sendEmail(getPlayerData(client).accountData.emailAddress, getPlayerData(client).accountData.name, `Confirm email on ${getServerName()}`, emailBodyText);
sendEmail(getPlayerData(client).accountData.emailAddress, getPlayerData(client).accountData.name, `Confirm email on ${getServerName()}`, emailBodyText);
}
// ===========================================================================
async function sendPasswordResetEmail(client, verificationCode) {
function sendPasswordResetEmail(client, verificationCode) {
let emailBodyText = getEmailConfig().bodyContent.confirmPasswordReset;
emailBodyText = emailBodyText.replace("{VERIFICATIONCODE}", verificationCode);
emailBodyText = emailBodyText.replace("{SERVERNAME}", getServerName());
await sendEmail(getPlayerData(client).accountData.emailAddress, getPlayerData(client).accountData.name, `Reset your password on ${getServerName()}`, emailBodyText);
sendEmail(getPlayerData(client).accountData.emailAddress, getPlayerData(client).accountData.name, `Reset your password on ${getServerName()}`, emailBodyText);
}
// ===========================================================================
async function verifyAccountEmail(accountData, verificationCode) {
function verifyAccountEmail(accountData, verificationCode) {
let emailVerificationCode = generateRandomString(10);
let emailBodyText = getEmailConfig().bodyContent.confirmEmail;
emailBodyText = emailBodyText.replace("{VERIFICATIONCODE}", emailVerificationCode);
emailBodyText = emailBodyText.replace("{SERVERNAME}", getServerName());
await sendEmail(getPlayerData(client).accountData.emailAddress, getPlayerData(client).accountData.name, `Confirm email on ${getServerName()}`, emailBodyText);
sendEmail(getPlayerData(client).accountData.emailAddress, getPlayerData(client).accountData.name, `Confirm email on ${getServerName()}`, emailBodyText);
getPlayerData(client).accountData.emailAddress = emailAddress;
getPlayerData(client).accountData.emailVerificationCode = module.hashing.sha512(emailVerificationCode);
@@ -1767,7 +1784,7 @@ async function verifyAccountEmail(accountData, verificationCode) {
// ===========================================================================
async function sendAccountLoginFailedNotification(emailAddress, name, ip, game = getGame()) {
function sendAccountLoginFailedNotification(emailAddress, name, ip, game = getGame()) {
let countryName = module.geoip.getCountryName(getGlobalConfig().geoIPCountryDatabaseFilePath, ip);
let subDivisionName = module.geoip.getSubdivisionName(getGlobalConfig().geoIPCityDatabaseFilePath, ip);
let cityName = module.geoip.getCityName(getGlobalConfig().geoIPCityDatabaseFilePath, ip);
@@ -1779,13 +1796,13 @@ async function sendAccountLoginFailedNotification(emailAddress, name, ip, game =
emailBodyText = emailBodyText.replace("{SERVERNAME}", getServerName());
emailBodyText = emailBodyText.replace("{TIMESTAMP}", new Date().toLocaleString('en-US'));
await sendEmail(emailAddress, name, `Login failed on ${getServerName()}`, emailBodyText);
sendEmail(emailAddress, name, `Login failed on ${getServerName()}`, emailBodyText);
return true;
}
// ===========================================================================
async function sendAccountLoginSuccessNotification(emailAddress, name, ip, game = getGame()) {
function sendAccountLoginSuccessNotification(emailAddress, name, ip, game = getGame()) {
let countryName = module.geoip.getCountryName(getGlobalConfig().geoIPCountryDatabaseFilePath, ip);
let subDivisionName = module.geoip.getSubdivisionName(getGlobalConfig().geoIPCityDatabaseFilePath, ip);
let cityName = module.geoip.getCityName(getGlobalConfig().geoIPCityDatabaseFilePath, ip);
@@ -1797,7 +1814,7 @@ async function sendAccountLoginSuccessNotification(emailAddress, name, ip, game
emailBodyText = emailBodyText.replace("{SERVERNAME}", getServerName());
emailBodyText = emailBodyText.replace("{TIMESTAMP}", new Date().toLocaleString('en-US'));
await sendEmail(emailAddress, name, `Login successful on ${getServerName()}`, emailBodyText);
sendEmail(emailAddress, name, `Login successful on ${getServerName()}`, emailBodyText);
return true;
}
@@ -1843,13 +1860,13 @@ function isPlayerATester(client) {
// ===========================================================================
async function sendAccountTwoFactorAuthCode(emailAddress, name, twoFactorAuthCode) {
function sendAccountTwoFactorAuthCode(emailAddress, name, twoFactorAuthCode) {
let emailBodyText = getEmailConfig().bodyContent.twoFactorAuthentication;
emailBodyText = emailBodyText.replace("{2FACODE}", twoFactorAuthCode);
emailBodyText = emailBodyText.replace("{GAMENAME}", getGameName(getGame()));
emailBodyText = emailBodyText.replace("{SERVERNAME}", getServerName());
await sendEmail(emailAddress, name, `Login code for ${getServerName()}`, emailBodyText);
sendEmail(emailAddress, name, `Login code for ${getServerName()}`, emailBodyText);
return true;
}

View File

@@ -40,6 +40,7 @@ let serverBitFlagKeys = {
"Developer",
"ManageNPCs",
"ManageRaces",
"ManagePayPhones",
],
moderationFlagKeys: [
"None",
@@ -261,14 +262,14 @@ let serverBitFlagKeys = {
"EnterJobVehicleForRoute",
"JobLocations",
"JobRouteStart",
"PayPhoneFirstUse",
],
jobRankKeys: [
jobFlagKeys: [
"None",
"PublicAccess",
"WhiteList",
"BlackList",
"AddMember",
"RemoveMember",
"SuspendMember",
"SetRank",
"SetPay",
"ManageUniforms",
"ManageEquipment",
"ManageVehicles",
@@ -293,7 +294,7 @@ function initBitFlagScript() {
serverBitFlags.npcTriggerConditionTypes = createBitFlagTable(serverBitFlagKeys.npcTriggerConditionTypeKeys);
serverBitFlags.npcTriggerResponseTypes = createBitFlagTable(serverBitFlagKeys.npcTriggerResponseTypeKeys);
serverBitFlags.seenActionTips = createBitFlagTable(serverBitFlagKeys.seenActionTipsKeys);
serverBitFlags.jobRankFlags = createBitFlagTable(serverBitFlagKeys.jobRankKeys);
serverBitFlags.jobFlags = createBitFlagTable(serverBitFlagKeys.jobFlagKeys);
logToConsole(LOG_INFO, "[V.RP.BitFlag]: Bit flag script initialized successfully!");
return true;
}
@@ -420,6 +421,20 @@ function getClanFlagValue(flagName) {
// ===========================================================================
function getJobFlagValue(flagName) {
if (flagName == "All") {
return -1;
}
if (typeof getServerBitFlags().jobFlags[flagName] == "undefined") {
return false;
}
return getServerBitFlags().jobFlags[flagName];
}
// ===========================================================================
function getAccountSettingsFlagValue(flagName) {
if (flagName == "All") {
return -1;

View File

@@ -224,7 +224,7 @@ function loadBusinessesFromDatabase() {
if (dbAssoc.length > 0) {
for (let i in dbAssoc) {
let tempBusinessData = new BusinessData(dbAssoc[i]);
tempBusinessData.locations = loadBusinessLocationsFromDatabase(tempBusinessData.databaseId);
//tempBusinessData.locations = loadBusinessLocationsFromDatabase(tempBusinessData.databaseId);
//tempBusinessData.gameScripts = loadBusinessGameScriptsFromDatabase(tempBusinessData.databaseId);
tempBusinesses.push(tempBusinessData);
logToConsole(LOG_VERBOSE, `[V.RP.Business]: Business '${tempBusinessData.name}' (ID ${tempBusinessData.databaseId}) loaded from database successfully!`);
@@ -1114,6 +1114,8 @@ function setBusinessInteriorTypeCommand(command, params, client) {
getBusinessData(businessId).exitScene = "";
getBusinessData(businessId).exitPickupModel = -1;
getBusinessData(businessId).customInterior = false;
getBusinessData(businessId).exitScene = "";
getBusinessData(businessId).entranceScene = "";
messageAdmins(`{adminOrange}${getPlayerName(client)}{MAINCOLOUR} removed business {businessBlue}${getBusinessData(businessId).name}{MAINCOLOUR} interior`, true);
return false;
}
@@ -1138,11 +1140,8 @@ function setBusinessInteriorTypeCommand(command, params, client) {
getBusinessData(businessId).customInterior = getGameConfig().interiors[getGame()][typeParam][2];
if (isGameFeatureSupported("interiorScene")) {
if (isMainWorldScene(getPlayerData(client).scene)) {
getBusinessData(businessId).exitScene = getGameConfig().mainWorldScene[getGame()];
} else {
getBusinessData(businessId).exitScene = getGameConfig().interiors[getGame()][typeParam][3];
}
getBusinessData(businessId).exitScene = getGameConfig().interiors[getGame()][typeParam][3];
getBusinessData(businessId).entranceScene = getPlayerData(client).scene;
}
}
@@ -1287,6 +1286,8 @@ function giveDefaultItemsToBusinessCommand(command, params, client) {
return false;
}
saveBusinessToDatabase(businessId);
if (isNull(getGameConfig().defaultBusinessItems[getGame()][typeParam])) {
messagePlayerError(client, "Invalid business items type! Use a business items type name");
let businessItemTypes = Object.keys(getGameConfig().defaultBusinessItems[getGame()]);
@@ -2021,7 +2022,7 @@ function spawnBusinessEntrancePickup(businessId) {
// return false;
//}
logToConsole(LOG_VERBOSE, `[V.RP.Job]: Creating entrance pickup for business ${businessData.name}`);
logToConsole(LOG_VERBOSE, `[V.RP.Business]: Creating entrance pickup for business ${businessData.name} (${businessData.databaseId})`);
if (areServerElementsSupported() && getGame() != V_GAME_MAFIA_ONE && getGame() != V_GAME_GTA_IV) {
let entrancePickup = null;
@@ -2271,9 +2272,8 @@ function deleteBusiness(businessId, whoDeleted = 0) {
}
removePlayersFromBusiness(businessId);
getServerData().businesses.splice(businessId, 1);
updateBusinessPickupLabelData(businessId);
updateBusinessPickupLabelData(businessId, true);
return true;
}
@@ -2619,6 +2619,14 @@ function buyFromBusinessCommand(command, params, client) {
return false;
}
let useType = getItemTypeData(getItemData(getBusinessData(businessId).floorItemCache[itemSlot - 1]).itemTypeIndex).useType;
if (useType == V_ITEM_USE_TYPE_WEAPON || V_ITEM_USE_TYPE_TAZER || useType == V_ITEM_USE_TYPE_AMMO_CLIP) {
if (isPlayerWeaponBanned(client) && !isPlayerExemptFromAntiCheat(client)) {
messagePlayerError(client, getLocaleString(client, "WeaponBanned"));
return false;
}
}
let amount = 1;
if (areThereEnoughParams(params, 2, " ")) {
amount = toInteger(getParam(params, " ", 2)) || 1;
@@ -2643,12 +2651,12 @@ function buyFromBusinessCommand(command, params, client) {
let itemName = getItemTypeData(getItemData(getBusinessData(businessId).floorItemCache[itemSlot - 1]).itemTypeIndex).name;
if (getPlayerCurrentSubAccount(client).cash < totalCost) {
messagePlayerError(client, getLocaleString(client, "NotEnoughCashNeedAmountMore", `{ALTCOLOUR}${getBusinessData(businessId).floorItemCache[itemSlot - 1].buyPrice * amount - getPlayerCurrentSubAccount(client).cash}{MAINCOLOUR}`));
messagePlayerError(client, getLocaleString(client, "NotEnoughCashNeedAmountMore", `{ALTCOLOUR}${totalCost - getPlayerCurrentSubAccount(client).cash}{MAINCOLOUR}`));
return false;
}
takePlayerCash(client, totalCost);
createItem(getItemData(getBusinessData(businessId).floorItemCache[itemSlot - 1]).itemTypeIndex, getItemData(getBusinessData(businessId).floorItemCache[itemSlot - 1]).value, V_ITEM_OWNER_PLAYER, getPlayerCurrentSubAccount(client).databaseId, amount);
let itemIndex = createItem(getItemData(getBusinessData(businessId).floorItemCache[itemSlot - 1]).itemTypeIndex, getItemData(getBusinessData(businessId).floorItemCache[itemSlot - 1]).value, V_ITEM_OWNER_PLAYER, getPlayerCurrentSubAccount(client).databaseId, amount);
cachePlayerHotBarItems(client);
getBusinessData(businessId).till = getBusinessData(businessId).till + totalCost;
@@ -2657,14 +2665,6 @@ function buyFromBusinessCommand(command, params, client) {
deleteItem(getBusinessData(businessId).floorItemCache[itemSlot - 1]);
}
let useType = getItemTypeData(getItemData(getBusinessData(businessId).floorItemCache[itemSlot - 1]).itemTypeIndex).useType;
if (useType == V_ITEM_USE_TYPE_WEAPON || V_ITEM_USE_TYPE_TAZER || useType == V_ITEM_USE_TYPE_AMMO_CLIP) {
if (isPlayerWeaponBanned(client) && !isPlayerExemptFromAntiCheat(client)) {
messagePlayerError(client, getLocaleString(client, "WeaponBanned"));
return false;
}
}
//messagePlayerSuccess(client, `You bought ${amount} {ALTCOLOUR}${itemName} {MAINCOLOUR}for ${totalCost} ${priceEach}`);
meActionToNearbyPlayers(client, `buys a ${itemName}`);
@@ -2677,7 +2677,7 @@ function buyFromBusinessCommand(command, params, client) {
}
}
markPlayerActionTipSeen(client, "ViewInventory");
logBusinessItemPurchase(getBusinessData(businessId).databaseId, getPlayerCurrentSubAccount(client).databaseId, getItemData(itemIndex).databaseId);
}
// ===========================================================================
@@ -2720,7 +2720,7 @@ function setBusinessItemSellPriceCommand(command, params, client) {
getItemData(getBusinessData(businessId).floorItemCache[itemSlot - 1]).buyPrice = newPrice;
messagePlayerSuccess(client, `You changed the price of the {ALTCOLOUR}${getItemTypeData(getItemData(getBusinessData(businessId).floorItemCache[itemSlot - 1]).itemTypeIndex).name}'s {MAINCOLOUR}in slot {ALTCOLOUR}${itemSlot} {MAINCOLOUR}from ${getCurrencyString(oldPrice)} to ${getCurrencyString(newprice)}`);
messagePlayerSuccess(client, `You changed the price of the {ALTCOLOUR}${getItemTypeData(getItemData(getBusinessData(businessId).floorItemCache[itemSlot - 1]).itemTypeIndex).name}'s {MAINCOLOUR}in slot {ALTCOLOUR}${itemSlot} {MAINCOLOUR}from ${getCurrencyString(oldPrice)} to ${getCurrencyString(newPrice)}`);
}
// ===========================================================================
@@ -2870,12 +2870,18 @@ function getBusinessIdFromDatabaseId(databaseId) {
// ===========================================================================
// Updates all pickup data for a business by businessId
function updateBusinessPickupLabelData(businessId) {
function updateBusinessPickupLabelData(businessId, deleted = false) {
let businessData = false;
if (deleted == false) {
businessData = getBusinessData(businessId);
}
if (!areServerElementsSupported() || getGame() == V_GAME_MAFIA_ONE || getGame() == V_GAME_GTA_IV) {
if (getBusinessData(businessId) == false) {
sendBusinessToPlayer(null, businessId, true, "", false, -1, -1, 0, 0, false, false, false);
if (businessData == false) {
sendBusinessToPlayer(null, businessId, true, "", false, -1, -1, 0, 0, false, false, false, 0);
} else {
sendBusinessToPlayer(null, businessId, false, getBusinessData(businessId).name, getBusinessData(businessId).entrancePosition, getBusinessEntranceBlipModelForNetworkEvent(businessId), getBusinessEntrancePickupModelForNetworkEvent(businessId), getBusinessData(businessId).buyPrice, getBusinessData(businessId).rentPrice, getBusinessData(businessId).hasInterior, getBusinessData(businessId).locked, doesBusinessHaveAnyItemsToBuy(businessId));
sendBusinessToPlayer(null, businessId, false, businessData.name, businessData.entrancePosition, getBusinessEntranceBlipModelForNetworkEvent(businessId), getBusinessEntrancePickupModelForNetworkEvent(businessId), businessData.buyPrice, businessData.rentPrice, businessData.hasInterior, businessData.locked, doesBusinessHaveAnyItemsToBuy(businessId), businessData.entranceFee);
}
return false;
}
@@ -3242,4 +3248,61 @@ function getBusinessEntrancePickupModelForNetworkEvent(businessIndex) {
return pickupModelId;
}
// ===========================================================================
function getBusinessesInRange(position, distance) {
return getServerData().businesses.filter((business) => getDistance(position, business.entrancePosition) <= distance);
}
// ===========================================================================
function getNearbyBusinessesCommand(command, params, client) {
let distance = 10.0;
if (!areParamsEmpty(params)) {
distance = getParam(params, " ", 1);
}
if (isNaN(distance)) {
messagePlayerError(client, "The distance must be a number!");
return false;
}
distance = toFloat(distance);
if (distance <= 0) {
messagePlayerError(client, "The distance must be more than 0!");
return false;
}
let nearbyBusinesses = getBusinessesInRange(getPlayerPosition(client), distance);
if (nearbyBusinesses.length == 0) {
messagePlayerAlert(client, getLocaleString(client, "NoBusinessesWithinRange", distance));
return false;
}
let businessesList = nearbyBusinesses.map(function (x) {
return `{chatBoxListIndex}${x.index}: {MAINCOLOUR}${x.name} {mediumGrey}(${toFloat(getDistance(getPlayerPosition(client), x.entrancePosition)).toFixed(2)} ${toLowerCase(getLocaleString(client, "Meters"))} ${toLowerCase(getGroupedLocaleString(client, "CardinalDirections", getCardinalDirectionName(getCardinalDirection(getPlayerPosition(client), x.entrancePosition))))})`;
});
let chunkedList = splitArrayIntoChunks(businessesList, 4);
messagePlayerNormal(client, makeChatBoxSectionHeader(getLocaleString(client, "HeaderBusinessesInRangeList", `${distance} ${toLowerCase(getLocaleString(client, "Meters"))}`)));
for (let i in chunkedList) {
messagePlayerInfo(client, chunkedList[i].join(", "));
}
}
// ===========================================================================
function logBusinessItemPurchase(businessId, purchaserId, itemId) {
if (getServerConfig().devServer) {
return false;
}
quickDatabaseQuery(`INSERT INTO log_biz_buy (log_biz_buy_biz, log_biz_buy_who, log_biz_buy_item, log_biz_buy_when) VALUES (${businessId}, ${purchaserId}, ${itemId}, UNIX_TIMESTAMP())`);
logItemMove(itemId, V_ITEM_OWNER_BIZFLOOR, businessId, V_ITEM_OWNER_PLAYER, purchaserId)
}
// ===========================================================================

View File

@@ -50,14 +50,35 @@ function processPlayerChat(client, messageText) {
messageText = messageText.substring(0, 128);
switch (getGlobalConfig().mainChatType) {
if (getPlayerData(client).usingPayPhone != -1 && getPayPhoneData(getPlayerData(client).usingPayPhone).state == V_PAYPHONE_STATE_ACTIVE_CALL) {
messagePlayerPhoneCall(client, getPlayerData(client).payPhoneOtherPlayer, messageText);
return true;
}
switch (getServerConfig().normalChatType) {
case V_CHAT_TYPE_TALK:
talkToNearbyPlayers(client, messageText);
break;
case V_CHAT_TYPE_SHOUT:
shoutToNearbyPlayers(client, messageText);
break;
case V_CHAT_TYPE_WHISPER:
whisperToNearbyPlayers(client, messageText);
break;
case V_CHAT_TYPE_LOCAL:
oocToNearbyPlayers(client, messageText);
break;
case V_CHAT_TYPE_NONE:
messagePlayerError(client, getLocaleString(client, "NormalChatDisabled"));
break;
case V_CHAT_TYPE_GLOBAL:
default:
chatToAllPlayers(client, messageTest);
oocToAllPlayers(client, messageText);
break;
}
} else {
@@ -68,7 +89,7 @@ function processPlayerChat(client, messageText) {
let clients = getClients();
for(let i in clients) {
let translatedText;
translatedText = await translateMessage(messageText, getPlayerData(client).locale, getPlayerData(clients[i]).locale);
translatedText = 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"));
@@ -80,7 +101,51 @@ function processPlayerChat(client, messageText) {
// ===========================================================================
function globalOOCCommand(command, params, client) {
if (isPlayerMuted(client)) {
messagePlayerError(client, getLocaleString(client, "MutedCantChat"));
return false;
}
if (areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
if (!getServerConfig().globalChatEnabled) {
messagePlayerError(client, getLocaleString(client, "GlobalChatDisabled"));
return false;
}
oocToAllPlayers(client, params);
return true;
}
// ===========================================================================
function localOOCCommand(command, params, client) {
if (isPlayerMuted(client)) {
messagePlayerError(client, getLocaleString(client, "MutedCantChat"));
return false;
}
if (areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
oocToNearbyPlayers(client, params);
return true;
}
// ===========================================================================
function meActionCommand(command, params, client) {
if (isPlayerMuted(client)) {
messagePlayerError(client, getLocaleString(client, "MutedCantChat"));
return false;
}
if (areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
@@ -200,7 +265,7 @@ function adminChatCommand(command, params, client) {
}
}
messageDiscordAdminChannel(`${getPlayerData(client).accountData.staffTitle} ${getPlayerData(client).accountData.name}: ${messageText}`);
messageDiscordAdminChannel(`${getPlayerData(client).accountData.staffTitle} ${getPlayerData(client).accountData.name}: ${params}`);
}
// ===========================================================================
@@ -216,6 +281,16 @@ function clanChatCommand(command, params, client) {
return false;
}
if (getPlayerClan(client) == -1) {
messagePlayerError(client, getLocaleString(client, "InvalidClan"));
return false;
}
if (getClanData(getPlayerClan) == false) {
messagePlayerError(client, getLocaleString(client, "InvalidClan"));
return false;
}
clanChat(client, params);
}
@@ -437,9 +512,24 @@ function canPlayerUseMegaphone(client) {
// ===========================================================================
function chatToAllPlayers(client, messageText) {
messagePlayerNormal(null, `💬 ${getCharacterFullName(client)}: {MAINCOLOUR}${messageText}`, getPlayerColour(client));
messageDiscordChatChannel(`💬 ${getCharacterFullName(client)}: ${messageText}`);
function oocToAllPlayers(client, messageText) {
messagePlayerNormal(null, `💬 ${getCharacterFullName(client)}: {MAINCOLOUR}(( ${messageText} ))`, getPlayerColour(client));
messageDiscordChatChannel(`💬 ${getCharacterFullName(client)}: (( ${messageText} ))`);
}
// ===========================================================================
function oocToNearbyPlayers(client, messageText) {
let clients = getClients();
for (let i in clients) {
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]))) {
messagePlayerNormal(clients[i], `💬 ${getCharacterFullName(client)}: {lightGrey}(( ${messageText} ))`, getPlayerColour(client));
}
}
}
messageDiscordChatChannel(`💬 ${getCharacterFullName(client)}: (( ${messageText} ))`);
}
// ===========================================================================

View File

@@ -23,11 +23,15 @@ class ClanData {
this.colour = COLOUR_WHITE;
this.colours = [];
this.initialRank = 0;
this.members = [];
this.ranks = [];
this.needsSaved = false;
this.motd = false;
/** @type {Array.<ClanMemberData>} */
this.members = [];
/** @type {Array.<ClanRankData>} */
this.ranks = [];
if (dbAssoc) {
this.databaseId = toInteger(dbAssoc["clan_id"]);
this.name = dbAssoc["clan_name"];
@@ -311,7 +315,7 @@ function deleteClanCommand(command, params, client) {
// ===========================================================================
function setClanOwnerCommand(command, params, client) {
if (!doesPlayerHaveClanPermission(client, getClanFlagValue("owner"))) {
if (!doesPlayerHaveClanPermission(client, getClanFlagValue("Owner"))) {
messagePlayerError(client, "You must be the clan owner to use this command!");
return false;
}
@@ -334,18 +338,20 @@ function setClanOwnerCommand(command, params, client) {
return false;
}
let highestRankIndex = getHighestClanRank(clanIndex);
getClanData(clanIndex).owner = getPlayerCurrentSubAccount(targetClient).databaseId;
getPlayerCurrentSubAccount(targetClient).clan = getClanData(clanIndex).databaseId;
getPlayerCurrentSubAccount(targetClient).clanRank = getHighestClanRank(clanIndex);
getPlayerCurrentSubAccount(targetClient).clanIndex = getClanIndexFromDatabaseId(clanIndex)
getPlayerCurrentSubAccount(targetClient).clanRankIndex = getClanRankIndexFromDatabaseId(clanIndex, getPlayerCurrentSubAccount(targetClient).clanRank);
getPlayerCurrentSubAccount(targetClient).clanIndex = getClanIndexFromDatabaseId(clanIndex);
getPlayerCurrentSubAccount(targetClient).clanRank = getClanRankData(clanIndex, highestRankIndex).databaseId;
getPlayerCurrentSubAccount(targetClient).clanRankIndex = highestRankIndex;
getClanData(clanIndex).needsSaved = true;
getPlayerCurrentSubAccount(targetClient).clan = getClanData(clanIndex).databaseId;
getPlayerCurrentSubAccount(targetClient).clanFlags = getClanFlagValue("All");
//messageAdmins(`{adminOrange}${getPlayerName(client)} {MAINCOLOUR}set clan {clanOrange}${getClanData(clanIndex).name} {MAINCOLOUR}owner to {ALTCOLOUR}${getCharacterFullName(targetClient)}`);
messagePlayerSuccess(client, `You changed the clan owner to {ALTCOLOUR}${getCharacterFullName(targetClient)}`);
messagePlayerSuccess(client, `You changed clan {clanOrange}${getClanData(clanIndex).name}'s {MAINCOLOUR}owner to {ALTCOLOUR}${getCharacterFullName(targetClient)}`);
}
// ===========================================================================
@@ -1047,7 +1053,12 @@ function createClan(name) {
let tempClan = new ClanData(false);
tempClan.databaseId = getDatabaseInsertId(dbConnection);
tempClan.name = name;
getServerData().clans.push(tempClan);
let clanId = getServerData().clans.push(tempClan);
let tempDefaultRank = new ClanRankData(false);
tempDefaultRank.name = "Default Rank";
tempDefaultRank.needsSaved = true;
getServerData().clans[clanId - 1].ranks.push(tempDefaultRank);
setAllClanDataIndexes();
}
@@ -1521,7 +1532,7 @@ function getLowestClanRank(clanIndex) {
// ===========================================================================
function getHighestJobRank(clanIndex) {
function getHighestClanRank(clanIndex) {
let highestRank = 0;
for (let i in getServerData().clans[clanIndex].ranks) {
if (getClanRankData(clanIndex, i).level > getClanRankData(clanIndex, highestRank).level) {
@@ -1531,4 +1542,4 @@ function getHighestJobRank(clanIndex) {
return highestRank;
}
// ===========================================================================
// ===========================================================================

View File

@@ -16,12 +16,13 @@ const V_RETURNTO_TYPE_SKINSELECT = 2; // "Return to" data is from skin
/**
* @class Representing extra data for a client
* @property {AccountData} accountData
* @property {Array.<SubAccountData>} subAccounts
*/
class ClientData {
constructor(client, accountData, subAccounts) {
/** @type {AccountData} */
this.accountData = accountData;
/** @type {Array.<SubAccountData>} */
this.subAccounts = subAccounts; // Characters
// General Info
@@ -129,6 +130,7 @@ class ClientData {
this.alcoholLevel = 0;
this.pedState = V_PEDSTATE_NONE;
this.promptType = V_PROMPT_NONE;
this.promptValue = 0;
this.privateMessageReplyTo = null;
this.enteringExitingProperty = null;
this.inProperty = null;
@@ -149,6 +151,12 @@ class ClientData {
this.casinoChips = 0; // This might become an item with a useId of a business (for chips belonging to specific casinos)
this.casinoCardHand = [];
this.casinoPlayingGame = V_CASINO_GAME_NONE;
// PayPhone
this.usingPayPhone = -1;
this.payPhoneOtherPlayer = null;
this.payPhoneCallStart = 0;
this.payPhoneInitiatedCall = false;
}
};

View File

@@ -147,7 +147,8 @@ function loadCommands() {
new CommandData("bizdelflooritems", deleteBusinessFloorItemsCommand, "", getStaffFlagValue("ManageItems"), true, true, "Destroys all items on the business floor (for-sale items)"),
new CommandData("bizdelstorageitems", deleteBusinessStorageItemsCommand, "", getStaffFlagValue("ManageItems"), true, true, "Destroys all items in the business's storage"),
new CommandData("bizdealership", setBusinessDealershipCommand, "", getStaffFlagValue("None"), true, true, "Sets the business's door label to vehicle dealership"),
//new CommandData("bizpaintball", setBusinessPaintBallCommand, "", getStaffFlagValue("None"), true, true, "Sets the business to a paintball arena"),
new CommandData("bizpaintball", setBusinessPaintBallCommand, "", getStaffFlagValue("None"), true, true, "Sets the business to a paintball arena"),
new CommandData("nearbiz", getNearbyBusinessesCommand, "[distance]", getStaffFlagValue("None"), true, true, "Shows all businesses within X meters"),
],
chat: [
new CommandData("me", meActionCommand, "<message>", getStaffFlagValue("None"), true, false, "Shows a custom action message in chat"),
@@ -167,6 +168,8 @@ function loadCommands() {
new CommandData("dm", privateMessageCommand, "<player name/id> <message>", getStaffFlagValue("None"), true, true, "Sends a private message to a player"),
new CommandData("msg", privateMessageCommand, "<player name/id> <message>", getStaffFlagValue("None"), true, true, "Sends a private message to a player"),
new CommandData("reply", replyToLastPrivateMessageCommand, "<message>", getStaffFlagValue("None"), true, true, "Replies to the last private message you received"),
new CommandData("b", localOOCCommand, "<message>", getStaffFlagValue("None"), true, true, "Local OOC (out of character) chat, shows to players in proximity"),
new CommandData("o", globalOOCCommand, "<message>", getStaffFlagValue("None"), true, true, "Global OOC (out of character) chat, shows to all players"),
],
clan: [
new CommandData("clans", listClansCommand, "[search text]", getStaffFlagValue("None"), true, true, "List clans (search by partial name, if provided)"),
@@ -195,10 +198,10 @@ function loadCommands() {
client: [],
colour: [],
command: [
new CommandData("cmdenabletype", enableAllCommandsByType, "<type>", getStaffFlagValue("Developer"), true, true, "Enables all commands by type."),
new CommandData("cmddisabletype", disableAllCommandsByType, "<type>", getStaffFlagValue("Developer"), true, true, "Disables all commands by type."),
new CommandData("cmdenable", enableCommand, "<command>", getStaffFlagValue("Developer"), true, true, "Enable a specific command"),
new CommandData("cmddisable", disableCommand, "<command>", getStaffFlagValue("Developer"), true, true, "Disables a specific command"),
new CommandData("cmdenabletype", enableAllCommandsByType, "<type>", getStaffFlagValue("ManageServer"), true, true, "Enables all commands by type."),
new CommandData("cmddisabletype", disableAllCommandsByType, "<type>", getStaffFlagValue("ManageServer"), true, true, "Disables all commands by type."),
new CommandData("cmdenable", enableCommand, "<command>", getStaffFlagValue("ManageServer"), true, true, "Enable a specific command"),
new CommandData("cmddisable", disableCommand, "<command>", getStaffFlagValue("ManageServer"), true, true, "Disables a specific command"),
],
config: [
new CommandData("settime", setTimeCommand, "<hour> [minute]", getStaffFlagValue("ManageWorld"), true, true, "Sets the time. Hours are required, minute is optional and will default to 0"),
@@ -236,7 +239,7 @@ function loadCommands() {
new CommandData("scode", executeServerCodeCommand, "<code>", getStaffFlagValue("Developer"), true, true, "Execute serverside code"),
new CommandData("ccode", executeClientCodeCommand, "<code>", getStaffFlagValue("Developer"), true, true, "Execute clientside code for a player"),
new CommandData("gmx", restartGameModeCommand, "", getStaffFlagValue("Developer"), true, true, "Restart this gamemode"),
new CommandData("saveall", saveServerDataCommand, "", getStaffFlagValue("Developer"), true, true, "Immediately save all data to database"),
new CommandData("saveall", saveServerDataCommand, "", getStaffFlagValue("ManageHouses") | getStaffFlagValue("ManageBusinesses") | getStaffFlagValue("ManageJobs") | getStaffFlagValue("ManagePayPhones"), true, true, "Immediately save all data to database"),
new CommandData("docmd", simulateCommandForPlayerCommand, "<player name/id> <command> [params]", getStaffFlagValue("Developer"), true, true, "Force a player to use a command"),
new CommandData("docmdall", simulateCommandForAllPlayersCommand, "<command> [params]", getStaffFlagValue("Developer"), true, true, "Force all players to use a command"),
new CommandData("addloglevel", addLogLevelCommand, "<log level name>", getStaffFlagValue("Developer"), true, true, "Adds a log level"),
@@ -247,7 +250,6 @@ function loadCommands() {
new CommandData("streamurlall", streamAudioURLToAllPlayersCommand, "<url> <volume>", getStaffFlagValue("Developer"), true, true, "Plays a URL radio stream for all players"),
new CommandData("streamnameall", streamAudioNameToAllPlayersCommand, "<name> <volume>", getStaffFlagValue("Developer"), true, true, "Plays an audio file stream for all players"),
new CommandData("forceresetpass", forceAccountPasswordResetCommand, "<account name>", getStaffFlagValue("Developer"), true, true),
new CommandData("fixblips", fixAllServerBlipsCommand, "", getStaffFlagValue("Developer"), true, true, "Clears and recreates all map blips"),
new CommandData("fixpickups", fixAllServerPickupsCommand, "", getStaffFlagValue("Developer"), true, true, "Clears and recreates all pickups"),
new CommandData("resetambience", resetAllServerAmbienceElementsCommand, "", getStaffFlagValue("ManageWorld"), true, true, "Clears all current server ambience elements (traffic, peds, etc)"),
@@ -260,11 +262,24 @@ function loadCommands() {
new CommandData("tax", taxInfoCommand, "", getStaffFlagValue("None"), true, true),
new CommandData("wealth", wealthInfoCommand, "", getStaffFlagValue("None"), true, true),
new CommandData("forcepayday", forcePlayerPayDayCommand, "<player name/id>", getStaffFlagValue("ManageServer"), true, true, "Gives a player an instant payday."),
new CommandData("setincomemultiplier", setGrossIncomeMultiplierCommand, "<amount>", getStaffFlagValue("ManageServer"), true, true, "Multiplies pay by this amount. 100% adds nothing extra"),
new CommandData("setinflation", setInflationMultiplierCommand, "<amount>", getStaffFlagValue("ManageServer"), true, true, "Sets the server inflation (in percent). 100% is no inflation"),
new CommandData("setincometax", setIncomeTaxCommand, "<amount>", getStaffFlagValue("ManageServer"), true, true, "Sets the server income tax (in percent). Players will be taxed this much when getting pay"),
new CommandData("sethouseupkeep", setHouseUpkeepCommand, "<amount>", getStaffFlagValue("ManageServer"), true, true, "Sets the base upkeep cost of a house"),
new CommandData("setbizupkeep", setBusinessUpkeepCommand, "<amount>", getStaffFlagValue("ManageServer"), true, true, "Sets the base upkeep cost of a business"),
new CommandData("setvehupkeep", setVehicleUpkeepCommand, "<amount>", getStaffFlagValue("ManageServer"), true, true, "Sets the base upkeep cost of a vehicle"),
new CommandData("setcurrencystring", setCurrencyStringCommand, "<string> MUST INCLUDE {AMOUNT}", getStaffFlagValue("ManageServer"), true, true, "Sets the currency string"),
new CommandData("setpassiveincome", setPassiveIncomeCommand, "<amount>", getStaffFlagValue("ManageServer"), true, true, "Sets the base upkeep cost of a vehicle"),
],
email: [
new CommandData("testemail", testEmailCommand, "<email address>", getStaffFlagValue("Developer"), true, true),
],
fishing: [],
fishing: [
//new CommandData("fish", castFishingLineCommand, "", getStaffFlagValue("None"), true, true, "Casts your fishing line into the water"),
//new CommandData("castline", castFishingLineCommand, "", getStaffFlagValue("None"), true, true, "Casts your fishing line into the water"),
//new CommandData("resetline", resetFishingLineCommand, "", getStaffFlagValue("None"), true, true, "Casts your fishing line into the water"),
],
forensics: [],
gate: [
new CommandData("gate", triggerGateCommand, "", getStaffFlagValue("None"), true, true, "Opens/closes the nearest gate"),
@@ -317,6 +332,7 @@ function loadCommands() {
new CommandData("houseentrance", moveHouseEntranceCommand, "", getStaffFlagValue("ManageHouses"), true, true, "Moves a house's entrance (outside/exterior location to enter the house)"),
new CommandData("houseexit", moveHouseExitCommand, "", getStaffFlagValue("ManageHouses"), true, true, "Moves a house's exit (inside/interior location to exit the house)"),
new CommandData("houseinttype", setHouseInteriorTypeCommand, "<interior template name/business id>", getStaffFlagValue("ManageHouses"), true, true, "Sets a house's interior to a pre-defined type"),
//new CommandData("nearhouse", getNearbyHousesCommand, "[distance]", getStaffFlagValue("None"), true, true, "Shows all houses within X meters"),
],
insurance: [],
item: [
@@ -333,7 +349,8 @@ function loadCommands() {
new CommandData("inv", listPlayerInventoryCommand, "", getStaffFlagValue("None"), true, false, "Shows the items in your inventory"),
new CommandData("inventory", listPlayerInventoryCommand, "", getStaffFlagValue("None"), true, false, "Shows the items in your inventory"),
new CommandData("items", listItemInventoryCommand, "", getStaffFlagValue("None"), true, false, "Shows the items in your inventory"),
new CommandData("items", listItemInventoryCommand, "", getStaffFlagValue("None"), true, false, "Shows the items stored in a container item"),
new CommandData("vehtrunk", listVehicleTrunkInventoryCommand, "", getStaffFlagValue("None"), true, false, "Shows the items in a vehicle's trunk"),
new CommandData("houseitems", listHouseInventoryCommand, "", getStaffFlagValue("None"), true, false, "Shows the items in the house's storage"),
new CommandData("bizstorage", listBusinessStorageInventoryCommand, "", getStaffFlagValue("None"), true, false, "Shows the items in the business's extra storage (not buyable)"),
new CommandData("bizfloor", listBusinessFloorInventoryCommand, "", getStaffFlagValue("None"), true, false, "Shows the items that can be bought from the business"),
@@ -376,7 +393,7 @@ function loadCommands() {
new CommandData("quitjob", quitJobCommand, "", getStaffFlagValue("None"), true, false, "Leave your job and be unemployed"),
new CommandData("uniform", jobUniformCommand, "[uniform]", getStaffFlagValue("None"), true, false, "Use a job uniform"),
new CommandData("equip", jobEquipmentCommand, "[equipment]", getStaffFlagValue("None"), true, false, "Get equipment for your job"),
new CommandData("jobrank", setPlayerJobRankCommand, "<player name/id> <rank name/id>", getStaffFlagValue("None"), true, true, "Sets a player's job rank"),
new CommandData("jobs", jobListCommand, "", getStaffFlagValue("None"), true, false, "Shows a list of all jobs"),
new CommandData("joblist", jobListCommand, "", getStaffFlagValue("None"), true, false, "Shows a list of all jobs"),
new CommandData("alljobs", jobListCommand, "", getStaffFlagValue("None"), true, false, "Shows a list of all jobs"),
@@ -443,6 +460,13 @@ function loadCommands() {
new CommandData("jobreloadall", reloadAllJobsCommand, "", getStaffFlagValue("ManageJobs"), true, false),
new CommandData("jobinfo", getJobInfoCommand, "", getStaffFlagValue("None"), true, true, "Get info for nearest or specified job"),
new CommandData("joblocinfo", getJobLocationInfoCommand, "", getStaffFlagValue("None"), true, true, "Get info for nearest or specified job location"),
new CommandData("jobroutes", getJobRoutesCommand, "", getStaffFlagValue("None"), true, false, "Shows a list of job routes for the nearest job location"),
new CommandData("jobrouteinfo", getJobRouteInfoCommand, "", getStaffFlagValue("None"), true, false, "Shows info about a job route"),
new CommandData("jobinvite", jobInviteCommand, "<player name/id>", getStaffFlagValue("None"), true, false, "Invites a player to a job"),
new CommandData("jobhire", jobInviteCommand, "<player name/id>", getStaffFlagValue("None"), true, false, "Invites a player to a job"),
new CommandData("jobuninvite", jobUninviteCommand, "<player name/id>", getStaffFlagValue("None"), true, false, "Removes a player from their job"),
new CommandData("jobfire", jobUninviteCommand, "<player name/id>", getStaffFlagValue("None"), true, false, "Removes a player from their job"),
],
keybind: [
new CommandData("bindkey", addKeyBindCommand, "<key id/name> <command> [params]", getStaffFlagValue("None"), true, false, "Binds a key to a command and optional parameters"),
@@ -480,6 +504,8 @@ function loadCommands() {
new CommandData("light", lightsCommand, "", getStaffFlagValue("None"), true, false, "Turns on and off the lights for your vehicle, house, or business"),
new CommandData("kill", suicideCommand, "", getStaffFlagValue("None"), true, false, "Kills yourself"),
new CommandData("suicide", suicideCommand, "", getStaffFlagValue("None"), true, false, "Kills yourself"),
new CommandData("scoreboard", scoreBoardCommand, "", getStaffFlagValue("None"), true, false, "Shows the scoreboard (key press only)"),
new CommandData("locate", locatePlayerCommand, "<player name/id>", getStaffFlagValue("None"), true, true, "Shows the distance and direction of another player"),
],
npc: [
new CommandData("addnpc", createNPCCommand, "<skin id/name>", getStaffFlagValue("ManageNPCs"), true, false, "Creates an NPC with the specified skin"),
@@ -492,6 +518,23 @@ function loadCommands() {
//new CommandData("npcrespawn", respawnNPCCommand, "", getStaffFlagValue("ManageNPCs"), true, false, "Respawns the nearest NPC"),
],
paintball: [],
payPhone: [
new CommandData("addpayphone", createPayPhoneCommand, "[number]", getStaffFlagValue("ManagePayPhones"), true, false, "Creates an payphone with optional number (random number if not added)"),
new CommandData("delpayphone", deletePayPhoneCommand, "[number]", getStaffFlagValue("ManagePayPhones"), true, false, "Deleted a payphone with number (optional, will use closest payphone if no number)"),
new CommandData("call", callPayPhoneCommand, "<player name/id>", getStaffFlagValue("None"), true, false, "Calls the player (nearest payphone or their cellphone if applicable"),
new CommandData("hangup", hangupPayPhoneCommand, "", getStaffFlagValue("None"), true, false, "Ends a payphone call"),
new CommandData("answer", answerPayPhoneCommand, "", getStaffFlagValue("None"), true, false, "Answer's a ringing phone"),
new CommandData("givephone", givePayPhoneToPlayerCommand, "<player name/id>", getStaffFlagValue("None"), true, false, "Gives a phone to another player to talk on the call"),
new CommandData("payphone", getPayPhoneNumberCommand, "", getStaffFlagValue("None"), true, false, "Shows a phone's number"),
new CommandData("number", getPayPhoneNumberCommand, "", getStaffFlagValue("None"), true, false, "Shows a phone's number"),
new CommandData("nearpayphone", getNearbyPayPhonesCommand, "[range]", getStaffFlagValue("None"), true, false, "Shows a list of all nearby phones within certain range"),
new CommandData("nearpayphones", getNearbyPayPhonesCommand, "[range]", getStaffFlagValue("None"), true, false, "Shows a list of all nearby phones within certain range"),
new CommandData("payphoneinfo", getPayPhoneInfoCommand, "[number]", getStaffFlagValue("None"), true, false, "Shows info of nearest payphone (or of payphone with number)"),
new CommandData("phoneinfo", getPayPhoneInfoCommand, "[number]", getStaffFlagValue("None"), true, false, "Shows info of nearest payphone (or of payphone with number)"),
new CommandData("resetpayphones", resetAllPayPhonesCommand, "", getStaffFlagValue("ManagePayPhones"), true, false, "Resets all payphone states"),
new CommandData("fixpayphones", resetAllPayPhonesCommand, "", getStaffFlagValue("ManagePayPhones"), true, false, "Resets all payphone states"),
//new CommandData("callphone", callPhoneNumberCommand, "<number>", getStaffFlagValue("None"), true, false, "Rings the payphone with number"),
],
race: [
// Unfinished!
//new CommandData("addrace", createRaceCommand, "<name>", getStaffFlagValue("ManageRaces"), true, false, "Creates a race"),
@@ -561,7 +604,7 @@ function loadCommands() {
new CommandData("plrstafftitle", setPlayerStaffTitleCommand, "", getStaffFlagValue("ManageAdmins"), true, true, "Sets a player's staff title."),
new CommandData("playerstafftitle", setPlayerStaffTitleCommand, "", getStaffFlagValue("ManageAdmins"), true, true, "Sets a player's staff title."),
new CommandData("stafftitle", setPlayerStaffTitleCommand, "", getStaffFlagValue("ManageAdmins"), true, true, "Sets a player's staff title."),
new CommandData("givemoney", givePlayerMoneyCommand, "<player name/id> <amount>", getStaffFlagValue("serverManager"), true, true),
new CommandData("givemoney", givePlayerMoneyCommand, "<player name/id> <amount>", getStaffFlagValue("ServerManager"), true, true),
new CommandData("nonrpname", forceCharacterNameChangeCommand, "<player name/id>", getStaffFlagValue("BasicModeration"), true, true, "Forces a player to change their current character's name."),
new CommandData("setname", forceCharacterNameCommand, "<player name/id> <first name> <last name>", getStaffFlagValue("BasicModeration"), true, true, "Changes a character's name directly."),
new CommandData("setskin", forcePlayerSkinCommand, "<player name/id> <skin id/name>", getStaffFlagValue("BasicModeration"), true, true, "Changes a character's skin."),
@@ -596,7 +639,9 @@ function loadCommands() {
new CommandData("biz", getPlayerCurrentBusinessCommand, "<player name/id>", getStaffFlagValue("BasicModeration"), true, true, "Gets which business a player is at/in"),
new CommandData("business", getPlayerCurrentBusinessCommand, "<player name/id>", getStaffFlagValue("BasicModeration"), true, true, "Gets which business a player is at/in"),
new CommandData("house", getPlayerCurrentHouseCommand, "<player name/id>", getStaffFlagValue("BasicModeration"), true, true, "Gets which house a player is at/in"),
//new CommandData("clearchat", clearChatCommand, "", getStaffFlagValue("None"), true, true, "Clears the chat"),
new CommandData("clearchat", clearChatCommand, "", getStaffFlagValue("BasicModeration"), true, true, "Clears the chat"),
new CommandData("forceresetpass", forceAccountPasswordResetCommand, "<player name/id>", getStaffFlagValue("ManageServer"), true, true),
new CommandData("chattype", setServerDefaultChatTypeCommand, "<chat type name>", getStaffFlagValue("ManageServer"), true, true, "Sets the normal chat type for the server"),
],
startup: [],
subAccount: [
@@ -884,11 +929,11 @@ function processPlayerCommand(command, params, client) {
return true;
}
let possibleAlias = getPlayerAliasForCommand(command);
if (possibleAlias) {
// Just change to the command the alias is for, then continue as normal
command = possibleAlias.forCommand;
}
//let possibleAlias = getPlayerAliasForCommand(client, command);
//if (possibleAlias) {
// // Just change to the command the alias is for, then continue as normal
// command = possibleAlias.forCommand;
//}
let commandData = getCommand(toLowerCase(command));
@@ -902,9 +947,9 @@ function processPlayerCommand(command, params, client) {
let possibleCommand = getCommandFromParams(command);
if (possibleCommand != false && doesPlayerHaveStaffPermission(client, getCommandRequiredPermissions(toLowerCase(possibleCommand.command)))) {
messagePlayerError(client, getLocaleString(client, "InvalidCommandPossibleMatchTip", `{ALTCOLOUR}/${command}{MAINCOLOUR}`, `{ALTCOLOUR}${toLowerCase(possibleCommand.command)}{MAINCOLOUR}`));
messagePlayerError(client, getLocaleString(client, "CommandNotFoundPossibleMatchTip", `{ALTCOLOUR}/${command}{MAINCOLOUR}`, `{ALTCOLOUR}${toLowerCase(possibleCommand.command)}{MAINCOLOUR}`));
} else {
messagePlayerError(client, getLocaleString(client, "InvalidCommandHelpTip", `{ALTCOLOUR}/${command}{MAINCOLOUR}`, `{ALTCOLOUR}/help{MAINCOLOUR}`));
messagePlayerError(client, getLocaleString(client, "CommandNotFoundHelpTip", `{ALTCOLOUR}/${command}{MAINCOLOUR}`, `{ALTCOLOUR}/help{MAINCOLOUR}`));
}
return false;
}
@@ -1097,4 +1142,30 @@ function getCommandFromParams(params) {
return false;
}
// ===========================================================================
function getPlayerAliasForCommand(client, command) {
return command;
}
// ===========================================================================
/**
* @return {Array.<CommandData>} Array of commands usable by staff flag
*/
function getCommandsUsableByStaffFlag(flagName) {
let usableCommands = [];
let commands = getCommands();
for (let i in commands) {
for (let j in commands[i]) {
if (hasBitFlag(commands[i][j].requiredStaffFlags, getStaffFlagValue(flagName))) {
usableCommands.push(commands[i][j]);
}
}
}
return usableCommands;
}
// ===========================================================================

View File

@@ -49,7 +49,6 @@ class ServerConfigData {
this.guiTextColourPrimary = [0, 0, 0];
this.guiTextColourSecondary = [0, 0, 0];
this.showLogo = true;
this.inflationMultiplier = 1;
this.testerOnly = false;
this.devServer = false;
this.nameTagDistance = 50.0;
@@ -80,12 +79,29 @@ class ServerConfigData {
this.useRealTime = false;
this.realTimeZone = 0;
this.normalChatType = V_CHAT_TYPE_GLOBAL;
this.discordConfig = {
sendEvents: true,
sendChat: true,
sendAdmin: true,
};
this.economy = {
inflationMultiplier: 1.0,
passiveIncomePerPayDay: 2000,
applyTax: true,
applyUpkeep: true,
grossIncomeMultiplier: 1.0,
incomeTaxRate: 0.7,
currencyString: "${AMOUNT}",
upKeepCosts: {
upKeepPerVehicle: 250,
upKeepPerHouse: 350,
upKeepPerBusiness: 600
}
};
if (dbAssoc) {
this.databaseId = dbAssoc["svr_id"];
this.newCharacter = {
@@ -136,12 +152,24 @@ class ServerConfigData {
this.economy = {
inflationMultiplier: toFloat(dbAssoc["svr_inflation_multiplier"]),
incomeTaxRate: toFloat(dbAssoc["svr_income_tax_rate"]),
passiveIncome: toFloat(dbAssoc["svr_passive_income"]),
}
incomeTaxRate: toFloat(dbAssoc["svr_tax_income"]),
passiveIncomePerPayDay: toFloat(dbAssoc["svr_passive_income"]),
applyTax: intToBool(dbAssoc["svr_tax_enabled"]),
applyUpkeep: intToBool(dbAssoc["svr_upkeep_enabled"]),
grossIncomeMultiplier: toFloat(dbAssoc["svr_gross_income_multiplier"]),
currencyString: toString(dbAssoc["svr_currency_string"]),
upKeepCosts: {
upKeepPerVehicle: toInteger(dbAssoc["svr_upkeep_veh"]),
upKeepPerHouse: toInteger(dbAssoc["svr_upkeep_house"]),
upKeepPerBusiness: toInteger(dbAssoc["svr_upkeep_biz"]),
}
};
this.devServer = intToBool(toInteger(server.getCVar("v_devserver")));
this.testerOnly = intToBool(toInteger(server.getCVar("v_testeronly")));
this.normalChatType = toInteger(dbAssoc["svr_chat_type"]);
this.globalChatEnabled = intToBool(dbAssoc["svr_chat_global_enabled"]);
}
}
};
@@ -155,12 +183,12 @@ let gameConfig = false;
let globalConfig = {
keyBind: [],
economy: {},
database: {},
locale: {},
accents: {},
discord: {},
email: {},
security: {},
accountPasswordHash: "SHA512",
npcFarProximity: 100,
npcMediumProximity: 40,
@@ -191,6 +219,7 @@ let globalConfig = {
vehicleRepairDistance: 5,
itemActionStateReset: 5000,
subAccountNameAllowedCharacters: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
alphaNumericCharacters: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
emailValidationRegex: /^([A-Za-z0-9_\-\.])+\@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,4})$/,
itemActionDelayExtraTimeout: 1000,
geoIPCountryDatabaseFilePath: "modules/geoip/geoip-country.mmdb",
@@ -210,7 +239,7 @@ let globalConfig = {
V_ITEM_USE_TYPE_VEHLIVERY,
V_ITEM_USE_TYPE_VEHTIRE,
],
vehicleInactiveRespawnDelay: 1800000, // 20 minutes
vehicleInactiveRespawnDelay: 1000 * 60 * 60, // 60 minutes
chatSectionHeaderLength: 96,
useServerSideVehiclePurchaseCheck: true,
useServerSideVehicleBurnCheck: false,
@@ -250,9 +279,10 @@ let globalConfig = {
"ChatBoxTimestamps",
"ChatEmoji",
],
mainChatType: V_CHAT_TYPE_TALK,
nightMapStartHour: 19,
nightMapEndHour: 7,
payPhoneGiveDistance: 2.5,
payPhoneAnswerDistance: 2.5,
};
// ===========================================================================
@@ -273,13 +303,6 @@ function loadGlobalConfig() {
thisResource.stop();
}
try {
getGlobalConfig().economy = loadEconomyConfig();
} catch (error) {
logToConsole(LOG_ERROR, `[V.RP.Config] Failed to load economy configuration. Error: ${error}`);
thisResource.stop();
}
try {
getGlobalConfig().locale = loadLocaleConfig();
} catch (error) {
@@ -315,6 +338,13 @@ function loadGlobalConfig() {
thisResource.stop();
}
try {
getGlobalConfig().security = loadSecurityConfig();
} catch (error) {
logToConsole(LOG_ERROR, `[V.RP.Config] Failed to load security configuration. Error: ${error}`);
thisResource.stop();
}
logToConsole(LOG_DEBUG, "[V.RP.Config] Loaded global configuration successfully!");
}
@@ -436,7 +466,6 @@ function saveServerConfigToDatabase() {
["svr_charselect_ped_rot_z", getServerConfig().characterSelectPedHeading],
["svr_charselect_int", getServerConfig().characterSelectInterior],
["svr_charselect_vw", getServerConfig().characterSelectDimension],
["svr_inflation_multiplier", getServerConfig().inflationMultiplier],
["svr_intro_music", getServerConfig().introMusicURL],
["svr_gui", getServerConfig().useGUI],
["svr_logo", getServerConfig().showLogo],
@@ -451,6 +480,17 @@ function saveServerConfigToDatabase() {
["svr_nametag_distance", getServerConfig().nameTagDistance],
["svr_real_time", boolToInt(getServerConfig().useRealTime)],
["svr_real_time_timezone", getServerConfig().realTimeZone],
["svr_inflation_multiplier", getServerConfig().economy.inflationMultiplier],
["svr_tax_income", getServerConfig().economy.incomeTaxRate],
["svr_passive_income", getServerConfig().economy.passiveIncomePerPayDay],
["svr_tax_enabled", boolToInt(getServerConfig().economy.applyTax)],
["svr_upkeep_enabled", boolToInt(getServerConfig().economy.applyUpkeep)],
["svr_gross_income_multiplier", getServerConfig().economy.grossIncomeMultiplier],
["svr_currency_string", getServerConfig().economy.currencyString],
["svr_upkeep_veh", getServerConfig().economy.upKeepCosts.upKeepPerVehicle],
["svr_upkeep_house", getServerConfig().economy.upKeepCosts.upKeepPerHouse],
["svr_upkeep_biz", getServerConfig().economy.upKeepCosts.upKeepPerBusiness],
["svr_chat_type", getServerConfig().normalChatType],
];
let dbQuery = null;
@@ -897,7 +937,7 @@ function setServerRealWorldTimeZoneCommand(command, params, client) {
* @return {bool} Whether or not the command was successful
*
*/
async function reloadServerConfigurationCommand(command, params, client) {
function reloadServerConfigurationCommand(command, params, client) {
serverConfig = loadServerConfigFromGameAndPort(server.game, server.port);
applyConfigToServer(serverConfig);
updateServerRules();
@@ -994,16 +1034,6 @@ function loadLocaleConfig() {
// ===========================================================================
function loadEconomyConfig() {
logToConsole(LOG_DEBUG, "[V.RP.Config] Loading economy configuration ...");
let economyConfig = JSON.parse(loadTextFile(`config/economy.json`));
if (economyConfig != null) {
return economyConfig;
}
}
// ===========================================================================
function loadAccentConfig() {
logToConsole(LOG_DEBUG, "[V.RP.Config] Loading accents configuration ...");
let accentConfig = JSON.parse(loadTextFile(`config/accents.json`));
@@ -1058,6 +1088,17 @@ function loadEmailConfig() {
// ===========================================================================
function loadSecurityConfig() {
logToConsole(LOG_DEBUG, "[V.RP.Config] Loading security configuration ...");
let securityConfig = JSON.parse(loadTextFile("config/security.json"));
if (securityConfig != null) {
return securityConfig;
}
return false;
}
// ===========================================================================
function doesServerHaveGUIEnabled() {
return getServerConfig().useGUI;
}
@@ -1130,6 +1171,12 @@ function getDatabaseConfig() {
// ===========================================================================
function getSecurityConfig() {
return getGlobalConfig().security;
}
// ===========================================================================
function loadServerConfig() {
logToConsole(LOG_DEBUG, "[V.RP.Config] Loading server configuration ...");

View File

@@ -9,13 +9,14 @@
let scriptVersion = "1.3";
let serverStartTime = 0;
let logLevel = LOG_INFO | LOG_DEBUG | LOG_VERBOSE;
let logLevel = LOG_INFO | LOG_DEBUG;
let playerResourceReady = new Array(server.maxClients).fill(false);
let playerResourceStarted = new Array(server.maxClients).fill(false);
let playerInitialized = new Array(server.maxClients).fill(false);
let playerGUI = new Array(server.maxClients).fill(false);
let defaultNoAccountId = 1;
let serverStarting = false;
// ===========================================================================
@@ -25,7 +26,7 @@ let defaultNoAccountId = 1;
* @property {Array.<ClientData>} clients
* @property {Array.<BusinessData>} businesses
* @property {Array.<HouseData>} houses
* @property {Array.<HouseData>} commands
* @property {Array} commands
* @property {Array.<ItemData>} items
* @property {Array.<ItemTypeData>} itemTypes
* @property {Array.<ClanData>} clans
@@ -35,6 +36,7 @@ let defaultNoAccountId = 1;
* @property {Array.<JobData>} jobs
* @property {Array.<GateData>} gates
* @property {Array.<RadioStationData>} radioStations
* @property {Array.<PayPhoneData>} payPhones
* @property {Array} locales
* @property {Array} localeStrings
* @property {Array} groundItemCache
@@ -60,6 +62,7 @@ let serverData = {
jobs: [],
gates: [],
radioStations: [],
payPhones: [],
localeStrings: {},
groundItemCache: [],
groundPlantCache: [],

View File

@@ -318,8 +318,8 @@ function executeServerCodeCommand(command, params, client) {
}
messagePlayerSuccess(client, "Server code executed!");
messagePlayerNormal(client, `Code: ${params}`, COLOUR_YELLOW);
messagePlayerNormal(client, `Returns: ${returnValue} (${typeof returnValue})`, COLOUR_YELLOW);
messagePlayerNormal(client, `Code: ${params}`, getColourByName("yellow"));
messagePlayerNormal(client, `Returns: ${returnValue} (${typeof returnValue})`, getColourByName("yellow"));
logToConsole(LOG_INFO, `Server code executed by ${getPlayerDisplayForConsole(client)}: ${params}`);
return true;
}
@@ -349,7 +349,7 @@ function executeClientCodeCommand(command, params, client) {
sendRunCodeToClient(targetClient, targetCode, client);
messagePlayerSuccess(client, `Executing client code for ${getPlayerName(targetClient)}`);
messagePlayerNormal(client, `Code: ${targetCode}`);
messagePlayerNormal(client, `Code: ${targetCode}`, getColourByName("yellow"));
return true;
}
@@ -448,7 +448,7 @@ function saveServerDataCommand(command, params, client) {
// ===========================================================================
async function testEmailCommand(command, params, client) {
function testEmailCommand(command, params, client) {
sendEmail(params, "Player", "Test email", "Just testing the email system for the server!");
return true;
@@ -483,7 +483,7 @@ function clientRunCodeSuccess(client, returnTo, returnVal) {
//messagePlayerSuccess(returnClient, `Client code executed for ${getPlayerName(client)}!`);
//messagePlayerNormal(returnClient, `Code: ${code}`, getColourByName("yellow"));
messagePlayerNormal(returnClient, `(${getPlayerName(client)}) Code returns: ${returnVal}`, getColourByName("white"));
messagePlayerNormal(returnClient, `(${getPlayerName(client)}) Code returns: ${returnVal}`, getColourByName("yellow"));
}
// ===========================================================================
@@ -548,7 +548,7 @@ function isDevelopmentServer() {
// ===========================================================================
async function migrateSubAccountsToPerServerData() {
function migrateSubAccountsToPerServerData() {
let dbConnection = connectToDatabase();
let dbAssoc = [];
@@ -569,7 +569,7 @@ async function migrateSubAccountsToPerServerData() {
// ===========================================================================
async function resetAllAccountsHotkeysToDefault() {
function resetAllAccountsHotkeysToDefault() {
let dbConnection = connectToDatabase();
let dbAssoc = [];
@@ -674,13 +674,6 @@ function resetAllServerAmbienceElementsCommand(command, params, client) {
// ===========================================================================
function reloadEconomyConfigurationCommand(command, params, client) {
getGlobalConfig().economy = loadEconomyConfig();
messageAdmins(`{adminOrange}${getPlayerName(client)} {MAINCOLOUR}has reloaded the economy settings`);
}
// ===========================================================================
function showLocalePickerTestCommand(command, params, client) {
showLocaleChooserForPlayer(client);
}

View File

@@ -31,10 +31,19 @@ function playerPayDay(client) {
let grossIncome = getPlayerData(client).payDayAmount;
// Passive income
grossIncome = Math.round(grossIncome + getGlobalConfig().economy.passiveIncomePerPayDay);
grossIncome = Math.round(grossIncome + getServerConfig().economy.passiveIncomePerPayDay);
// Job Pay
if (getPlayerJob(client) != -1) {
if (!getJobRankData(getPlayerJob(client), getPlayerJobRank(client))) {
grossIncome = grossIncome + 0;
} else {
grossIncome = Math.round(grossIncome + getJobRankData(getPlayerJob(client), getPlayerJobRank(client)).pay);
}
}
// Payday bonus
grossIncome = Math.round(grossIncome * getGlobalConfig().economy.grossIncomeMultiplier);
grossIncome = Math.round(grossIncome * getServerConfig().economy.grossIncomeMultiplier);
// Double bonus
if (isDoubleBonusActive()) {
@@ -50,7 +59,7 @@ function playerPayDay(client) {
messagePlayerInfo(client, `Taxes: {ALTCOLOUR}${getCurrencyString(incomeTaxAmount)}`);
messagePlayerInfo(client, `You receive: {ALTCOLOUR}${getCurrencyString(netIncome)}`);
if (netIncome < incomeTaxAmount) {
let totalCash = getPlayerCash(client);
let totalCash = getPlayerCurrentSubAccount(client);
let canPayNow = totalCash + netIncome;
if (incomeTaxAmount <= canPayNow) {
takePlayerCash(client, canPayNow);
@@ -75,6 +84,7 @@ function playerPayDay(client) {
}
givePlayerCash(client, netIncome);
getPlayerData(client).payDayAmount = 0;
}
// ===========================================================================
@@ -84,9 +94,9 @@ function calculateWealth(client) {
let houses = getAllHousesOwnedByPlayer(client);
let businesses = getAllBusinessesOwnedByPlayer(client);
let vehicleUpKeep = applyServerInflationMultiplier(vehicles.length * getGlobalConfig().economy.upKeepCosts.upKeepPerVehicle);
let houseUpKeep = applyServerInflationMultiplier(houses.length * getGlobalConfig().economy.upKeepCosts.upKeepPerHouse);
let businessUpKeep = applyServerInflationMultiplier(businesses.length * getGlobalConfig().economy.upKeepCosts.upKeepPerBusiness);
let vehicleUpKeep = applyServerInflationMultiplier(vehicles.length * getServerConfig().economy.upKeepCosts.upKeepPerVehicle);
let houseUpKeep = applyServerInflationMultiplier(houses.length * getServerConfig().economy.upKeepCosts.upKeepPerHouse);
let businessUpKeep = applyServerInflationMultiplier(businesses.length * getServerConfig().economy.upKeepCosts.upKeepPerBusiness);
return vehicleUpKeep + houseUpKeep + businessUpKeep;
}
@@ -94,7 +104,7 @@ function calculateWealth(client) {
// ===========================================================================
function calculateIncomeTax(amount) {
return amount * getGlobalConfig().economy.incomeTaxRate;
return amount * getServerConfig().economy.incomeTaxRate;
}
// ===========================================================================
@@ -117,26 +127,6 @@ function forcePlayerPayDayCommand(command, params, client) {
// ===========================================================================
function setPayDayBonusMultiplier(command, params, client) {
if (areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
let newMultiplier = params;
if (isNaN(newMultiplier)) {
messagePlayerError(client, getLocaleString(client, "AmountNotNumber"));
return false;
}
getGlobalConfig().economy.grossIncomeMultiplier = newMultiplier;
announceAdminAction(`PaydayBonusSet`, `{adminOrange}${getPlayerName(client)}{MAINCOLOUR}`, `{ALTCOLOUR}${newMultiplier * 100}%{MAINCOLOUR}`);
}
// ===========================================================================
function taxInfoCommand(command, params, client) {
let wealth = calculateWealth(client);
let tax = calculateIncomeTax(wealth);
@@ -168,19 +158,19 @@ function repossessFirstAsset(client) {
let vehicles = getAllVehiclesOwnedByPlayer(client);
if (vehicles.length > 0) {
deleteVehicle(vehicles[0]);
return getGlobalConfig().economy.upKeepCosts.upKeepPerVehicle;
return getServerConfig().economy.upKeepCosts.upKeepPerVehicle;
}
let houses = getAllHousesOwnedByPlayer(client);
if (houses.length > 0) {
deleteHouse(houses[0].index);
return getGlobalConfig().economy.upKeepCosts.upKeepPerHouse;
return getServerConfig().economy.upKeepCosts.upKeepPerHouse;
}
let businesses = getAllBusinessesOwnedByPlayer(client);
if (businesses.length > 0) {
deleteBusiness(businesses[0].index);
return getGlobalConfig().economy.upKeepCosts.upKeepPerBusiness;
return getServerConfig().economy.upKeepCosts.upKeepPerBusiness;
}
}
@@ -215,9 +205,202 @@ function isDoubleBonusActive() {
// ===========================================================================
function getCurrencyString(amount) {
let tempString = getGlobalConfig().economy.currencyString;
let tempString = getServerConfig().economy.currencyString;
tempString = tempString.replace("{AMOUNT}", toString(makeLargeNumberReadable(amount)));
return tempString;
}
// ===========================================================================
function setPassiveIncomeCommand(command, params, client) {
if (areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
if (isNaN(params)) {
messagePlayerError(client, "The amount needs to be a number!");
return false;
}
let amount = toInteger(params);
if (amount <= 0) {
messagePlayerError(client, "The amount can't be negative!");
return false;
}
getServerConfig().economy.passiveIncomePerPayDay = amount;
getServerConfig().needsSaved = true;
messageAdmins(`{adminOrange}${client.name}{MAINCOLOUR} set the passive income to {ALTCOLOUR}${getCurrencyString(amount)}`);
}
// ===========================================================================
function setCurrencyStringCommand(command, params, client) {
if (areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
if (params.indexOf("{AMOUNT}") == -1) {
messagePlayerError(client, "The currency text must include {AMOUNT}");
return false;
}
getServerConfig().economy.currencyString = params;
getServerConfig().needsSaved = true;
messageAdmins(`{adminOrange}${client.name}{MAINCOLOUR} set the to currency string to {ALTCOLOUR}${params}. Example: ${getCurrencyString(1000)}`);
}
// ===========================================================================
function setVehicleUpkeepCommand(command, params, client) {
if (areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
if (isNaN(params)) {
messagePlayerError(client, "The amount needs to be a number!");
return false;
}
let amount = toInteger(params);
if (amount <= 0) {
messagePlayerError(client, "The amount can't be negative!");
return false;
}
getServerConfig().economy.upKeepCosts.upKeepPerVehicle = amount;
getServerConfig().needsSaved = true;
messageAdmins(`{adminOrange}${client.name}{MAINCOLOUR} set the base upkeep per vehicle to {ALTCOLOUR}${getCurrencyString(amount)}`);
}
// ===========================================================================
function setBusinessUpkeepCommand(command, params, client) {
if (areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
if (isNaN(params)) {
messagePlayerError(client, "The amount needs to be a number!");
return false;
}
let amount = toInteger(params);
if (amount <= 0) {
messagePlayerError(client, "The amount can't be negative!");
return false;
}
getServerConfig().economy.upKeepCosts.upKeepPerBusiness = amount;
getServerConfig().needsSaved = true;
messageAdmins(`{adminOrange}${client.name}{MAINCOLOUR} set the base upkeep per business to {ALTCOLOUR}${getCurrencyString(amount)}`);
}
// ===========================================================================
function setHouseUpkeepCommand(command, params, client) {
if (areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
if (isNaN(params)) {
messagePlayerError(client, "The amount needs to be a number!");
return false;
}
let amount = toInteger(params);
if (amount <= 0) {
messagePlayerError(client, "The amount can't be negative!");
return false;
}
getServerConfig().economy.upKeepCosts.upKeepPerHouse = amount;
getServerConfig().needsSaved = true;
messageAdmins(`{adminOrange}${client.name}{MAINCOLOUR} set the base upkeep per house to {ALTCOLOUR}${getCurrencyString(amount)}`);
}
// ===========================================================================
function setIncomeTaxCommand(command, params, client) {
if (areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
if (isNaN(params)) {
messagePlayerError(client, "The amount needs to be a number!");
return false;
}
let amount = toInteger(params);
if (amount <= 0) {
messagePlayerError(client, "The amount can't be negative!");
return false;
}
getServerConfig().economy.incomeTaxRate = amount / 100;
getServerConfig().needsSaved = true;
messageAdmins(`{adminOrange}${client.name}{MAINCOLOUR} set the income tax rate to {ALTCOLOUR}${amount}%`);
}
// ===========================================================================
function setGrossIncomeMultiplierCommand(command, params, client) {
if (areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
if (isNaN(params)) {
messagePlayerError(client, "The amount needs to be a number!");
return false;
}
let amount = toInteger(params);
if (amount <= 0) {
messagePlayerError(client, "The amount can't be negative!");
return false;
}
getServerConfig().economy.grossIncomeMultiplier = amount / 100;
getServerConfig().needsSaved = true;
messageAdmins(`{adminOrange}${client.name}{MAINCOLOUR} set the gross income multiplier to {ALTCOLOUR}${amount}%`);
}
// ===========================================================================
function setInflationMultiplierCommand(command, params, client) {
if (areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
if (isNaN(params)) {
messagePlayerError(client, "The amount needs to be a number!");
return false;
}
let amount = toInteger(params);
if (amount <= 0) {
messagePlayerError(client, "The amount can't be negative!");
return false;
}
getServerConfig().economy.inflationMultiplier = amount / 100;
getServerConfig().needsSaved = true;
messageAdmins(`{adminOrange}${client.name}{MAINCOLOUR} set the server inflation {ALTCOLOUR}${amount}%`);
}
// ===========================================================================

View File

@@ -21,28 +21,28 @@ function initEmailScript() {
// ===========================================================================
async function sendEmail(toEmail, toName, subject, body) {
function sendEmail(toEmail, toName, subject, body) {
switch (getEmailConfig().method) {
case V_EMAIL_METHOD_SMTP_MODULE:
if (!checkForSMTPModule()) {
return false;
}
Promise.resolve().then(() => {
module.smtp.send(
getEmailConfig().smtp.host,
getEmailConfig().smtp.port,
intToBool(getEmailConfig().smtp.useTLS),
getEmailConfig().smtp.username,
getEmailConfig().smtp.password,
toEmail,
toName,
subject,
body,
getEmailConfig().smtp.from,
getEmailConfig().smtp.fromName
);
});
//Promise.resolve().then(() => {
module.smtp.send(
getEmailConfig().smtp.host,
getEmailConfig().smtp.port,
intToBool(getEmailConfig().smtp.useTLS),
getEmailConfig().smtp.username,
getEmailConfig().smtp.password,
toEmail,
toName,
subject,
body,
getEmailConfig().smtp.from,
getEmailConfig().smtp.fromName
);
//});
break;
case V_EMAIL_METHOD_GET_REQUEST:

View File

@@ -15,38 +15,6 @@ function initEventScript() {
// ===========================================================================
function addAllEventHandlers() {
addEventHandler("onResourceStart", onResourceStart);
addEventHandler("onResourceStop", onResourceStop);
addEventHandler("onProcess", onProcess);
addEventHandler("onPlayerConnect", onPlayerConnect);
addEventHandler("onPlayerJoin", onPlayerJoin);
addEventHandler("onPlayerJoined", onPlayerJoined);
addEventHandler("onPlayerChat", onPlayerChat);
addEventHandler("onPlayerQuit", onPlayerQuit);
addEventHandler("onElementStreamIn", onElementStreamIn);
addEventHandler("onElementStreamOut", onElementStreamOut);
addEventHandler("onPedSpawn", onPedSpawn);
if (getGame() <= V_GAME_GTA_IV) {
addEventHandler("onPedEnteredVehicleEx", onPedEnteredVehicle);
addEventHandler("onPedExitedVehicleEx", onPedExitedVehicle);
addEventHandler("onPedEnteredSphereEx", onPedEnteredSphere);
addEventHandler("onPedExitedSphereEx", onPedExitedSphere);
}
if (getGame() <= V_GAME_GTA_SA) {
addEventHandler("OnPickupCollected", onPedPickupPickedUp);
}
if (getGame() == V_GAME_MAFIA_ONE) {
addEventHandler("onPedEnteringVehicleEx", onPedEnteredVehicle);
addEventHandler("onPedExitingVehicleEx", onPedExitedVehicle);
}
}
// ===========================================================================
function onPlayerConnect(event, ipAddress, port) {
logToConsole(LOG_INFO, `[V.RP.Event] onPlayerConnect - Client connecting (IP: ${ipAddress})`);
//if(isIpAddressBanned(ipAddress)) {
@@ -148,7 +116,7 @@ function onPlayerQuit(event, client, quitReasonId) {
// ===========================================================================
async function onPlayerChat(event, client, messageText) {
function onPlayerChat(event, client, messageText) {
event.preventDefault();
processPlayerChat(client, messageText);
}
@@ -451,7 +419,7 @@ function onPedSpawn(ped) {
// ===========================================================================
async function onPlayerSpawn(client) {
function onPlayerSpawn(client) {
logToConsole(LOG_WARN | LOG_DEBUG, `[V.RP.Event] Player ${getPlayerDisplayForConsole(client)} spawned!`);
//logToConsole(LOG_DEBUG, `[V.RP.Event] Checking for ${getPlayerDisplayForConsole(client)}'s player ped`);
//if(getPlayerPed(client) == null) {
@@ -462,7 +430,7 @@ async function onPlayerSpawn(client) {
//logToConsole(LOG_DEBUG, `[V.RP.Event] ${getPlayerDisplayForConsole(client)}'s player ped is valid. Continuing spawn processing ...`);
if (areServerElementsSupported()) {
await waitUntil(() => client != null && getPlayerPed(client) != null);
waitUntil(() => client != null && getPlayerPed(client) != null);
}
stopRadioStreamForPlayer(client);
@@ -547,7 +515,7 @@ async function onPlayerSpawn(client) {
}
logToConsole(LOG_DEBUG, `[V.RP.Event] Sending ${getPlayerDisplayForConsole(client)}'s job type to their client (${getJobIndexFromDatabaseId(getPlayerCurrentSubAccount(client))})`);
sendPlayerJobType(client, getPlayerCurrentSubAccount(client).job);
sendPlayerJobType(client, (getPlayerCurrentSubAccount(client).job != 0) ? getPlayerCurrentSubAccount(client).jobIndex : -1);
if (isGameFeatureSupported("rendering2D")) {
logToConsole(LOG_DEBUG, `[V.RP.Event] Enabling all rendering states for ${getPlayerDisplayForConsole(client)}`);
@@ -587,6 +555,16 @@ async function onPlayerSpawn(client) {
let keyId = getPlayerKeyBindForCommand(client, "enter");
logToConsole(LOG_DEBUG, `[V.RP.Event] Sending custom enter property key ID (${keyId.key}, ${toUpperCase(getKeyNameFromId(keyId.key))}) to ${getPlayerDisplayForConsole(client)}`);
sendPlayerEnterPropertyKey(client, keyId.key);
} else {
sendPlayerEnterPropertyKey(client, -1);
}
if (!doesPlayerHaveKeyBindsDisabled(client) && doesPlayerHaveKeyBindForCommand(client, "scoreboard")) {
let keyId = getPlayerKeyBindForCommand(client, "scoreboard");
logToConsole(LOG_DEBUG, `[V.RP.Event] Sending scoreboard key ID (${keyId.key}, ${toUpperCase(getKeyNameFromId(keyId.key))}) to ${getPlayerDisplayForConsole(client)}`);
sendPlayerScoreBoardKey(client, keyId.key);
} else {
sendPlayerScoreBoardKey(client, -1);
}
sendPlayerChatBoxTimeStampsState(client, isPlayerAccountSettingEnabled(client, "ChatBoxTimestamps"));
@@ -638,6 +616,7 @@ async function onPlayerSpawn(client) {
logToConsole(LOG_DEBUG, `[V.RP.Event] Sending properties, jobs, and vehicles to ${getPlayerDisplayForConsole(client)} (no server elements)`);
sendAllBusinessesToPlayer(client);
sendAllHousesToPlayer(client);
sendAllPayPhonesToPlayer(client);
if (getGame() != V_GAME_GTA_IV) {
sendAllJobsToPlayer(client);
}
@@ -768,7 +747,7 @@ function onPedExitedVehicle(event, ped, vehicle, seat) {
getVehicleData(vehicle).lastActiveTime = getCurrentUnixTimestamp();
logToConsole(LOG_DEBUG, `[V.RP.Event] ${getPlayerDisplayForConsole(client)} exited a ${getVehicleName(vehicle)} (ID: ${vehicle.getData("v.rp.dataSlot")}, Database ID: ${getVehicleData(vehicle).databaseId})`);
logToConsole(LOG_DEBUG, `[V.RP.Event] ${getPlayerDisplayForConsole(client)} exited a ${getVehicleName(vehicle)} (ID: ${getVehicleDataIndexFromVehicle(vehicle)}, Database ID: ${getVehicleData(vehicle).databaseId})`);
}
}
}
@@ -803,7 +782,7 @@ function onPedEnteredVehicle(event, ped, vehicle, seat) {
return false;
}
logToConsole(LOG_DEBUG, `[V.RP.Event] ${getPlayerDisplayForConsole(client)} entered a ${getVehicleName(vehicle)} (ID: ${vehicle.getData("v.rp.dataSlot")}, Database ID: ${getVehicleData(vehicle).databaseId})`);
logToConsole(LOG_DEBUG, `[V.RP.Event] ${getPlayerDisplayForConsole(client)} entered a ${getVehicleName(vehicle)} (ID: ${getVehicleDataIndexFromVehicle(vehicle)}, Database ID: ${getVehicleData(vehicle).databaseId})`);
getPlayerData(client).lastVehicle = vehicle;
getVehicleData(vehicle).lastActiveTime = getCurrentUnixTimestamp();

View File

@@ -22,6 +22,29 @@ const V_FISHING_LINE_STATE_HOOKED = 5;
// ===========================================================================
class FishingLocationData {
constructor(dbAssoc = false) {
this.databaseId = 0;
this.serverId = 0;
this.index = -1;
this.position = toVector3(0.0, 0.0, 0.0);
this.enabled = false;
this.whoAdded = 0;
this.whenAdded = 0;
if (dbAssoc) {
this.databaseId = toInteger(dbAssoc["fish_loc_id"]);
this.serverId = toInteger(dbAssoc["fish_loc_server"]);
this.enabled = intToBool(dbAssoc["fish_loc_enabled"]);
this.position = toVector3(toFloat(dbAssoc["fish_loc_pos_x"]), toFloat(dbAssoc["fish_loc_pos_y"]), toFloat(dbAssoc["fish_loc_pos_z"]));
this.whoAdded = toInteger(dbAssoc["fish_loc_who_added"]);
this.whenAdded = toInteger(dbAssoc["fish_loc_when_added"]);
}
}
};
// ===========================================================================
let fishingCollectables = [
// Fish
["Salmon", V_FISHING_CATCH_TYPE_FISH],
@@ -63,7 +86,11 @@ let fishingAnimations = {
[V_GAME_GTA_SA]: {
"fishingLineCasting": "none",
"fishingLineReeling": "none",
}
},
//[V_GAME_MAFIA_ONE]: {
// "fishingLineCasting": "none",
// "fishingLineReeling": "none",
//}
};
// ===========================================================================
@@ -205,4 +232,16 @@ function isPlayerFishing(client) {
return (getPlayerData(client).fishingLineState != V_FISHING_LINE_STATE_NONE);
}
// ===========================================================================
function getClosestFishingLocation(position) {
let closest = 0;
for (let i in getServerData().fishingLocations) {
if (getDistance(position, getServerData().fishingLocations[i].position) < getDistance(position, getServerData().fishingLocations[closest].position))
closest = i;
}
return closest;
}
// ===========================================================================

View File

@@ -15,6 +15,7 @@ function initHelpScript() {
// ===========================================================================
let randomTips = [
/*
`{MAINCOLOUR}Look for yellow dots on your map for job locations.`,
`{MAINCOLOUR}You can set custom key binds. Use {ALTCOLOUR}/info keys {MAINCOLOUR} for details.`,
`{MAINCOLOUR}Use /notips if you don't want to see tips and extra information`,
@@ -43,6 +44,7 @@ let randomTips = [
//`{MAINCOLOUR}Banks can provide loans. Use {ALTCOLOUR}/info loans {MAINCOLOUR} for more details.`,
`{MAINCOLOUR}Want to make a clan? Use {ALTCOLOUR}/info clans {MAINCOLOUR} for details.`,
`{MAINCOLOUR}Legal weapons can be purchased at any ammunation.`,
*/
];
// ===========================================================================
@@ -87,13 +89,13 @@ function helpCommand(command, params, client) {
showRulesHelpMessage(client);
break;
case "website":
showWebsiteHelpMessage(client);
break;
//case "website":
// showWebsiteHelpMessage(client);
// break;
case "discord":
showDiscordHelpMessage(client);
break;
//case "discord":
// showDiscordHelpMessage(client);
// break;
case "anim":
case "anims":
@@ -147,6 +149,14 @@ function helpCommand(command, params, client) {
showWealthAndTaxHelpMessage(client);
break;
case "admin":
showAdminHelpMessage(client, getParam(params, " ", 2));
break;
//case "items":
// showItemsHelpMessage(client);
// break;
default:
showMainHelpMessage(client);
break;
@@ -184,8 +194,8 @@ function helpCommand(command, params, client) {
function showMainHelpMessage(client) {
messagePlayerInfo(client, makeChatBoxSectionHeader(getLocaleString(client, "HelpMainListHeader")));
messagePlayerNormal(client, `{clanOrange}• {MAINCOLOUR}Use /info <category> for commands and info. Example: {ALTCOLOUR}/info vehicle`);
messagePlayerNormal(client, `{clanOrange}• {MAINCOLOUR}Help Categories: [#A9A9A9]account, command, vehicle, job, chat, rules, website, animation`);
messagePlayerNormal(client, `{clanOrange}• [#A9A9A9]skin, mechanic, dealership, discord, colour, keybind`);
messagePlayerNormal(client, `{clanOrange}• {MAINCOLOUR}Help Categories: [#A9A9A9]account, command, vehicle, job, chat, rules, animation`);
messagePlayerNormal(client, `{clanOrange}• [#A9A9A9]skin, mechanic, dealership, colour, keybind`);
}
// ===========================================================================
@@ -252,6 +262,7 @@ function showRulesHelpMessage(client) {
// ===========================================================================
/*
function showWebsiteHelpMessage(client) {
messagePlayerInfo(client, makeChatBoxSectionHeader(getLocaleString(client, "HeaderWebsiteInfo")));
messagePlayerHelpContent(client, `{MAINCOLOUR}${server.getRule("Website")}`);
@@ -263,6 +274,7 @@ function showDiscordHelpMessage(client) {
messagePlayerInfo(client, makeChatBoxSectionHeader(getLocaleString(client, "HeaderDiscordInfo")));
messagePlayerHelpContent(client, `{MAINCOLOUR}${server.getRule("Discord")}`);
}
*/
// ===========================================================================
@@ -326,14 +338,39 @@ function showRadioHelpMessage(client) {
function showWealthAndTaxHelpMessage(client) {
messagePlayerInfo(client, makeChatBoxSectionHeader(getLocaleString(client, "HeaderWealthandTaxHelp")));
messagePlayerHelpContent(client, getGroupedLocaleString(client, "WealthAndTaxHelp", 0, `{ALTCOLOUR}${100 * getGlobalConfig().economy.incomeTaxRate}%{MAINCOLOUR}`));
messagePlayerHelpContent(client, getGroupedLocaleString(client, "WealthAndTaxHelp", 0, `{ALTCOLOUR}${100 * getServerConfig().economy.incomeTaxRate}%{MAINCOLOUR}`));
messagePlayerHelpContent(client, getGroupedLocaleString(client, "WealthAndTaxHelp", 1));
messagePlayerHelpContent(client, getGroupedLocaleString(client, "WealthAndTaxHelp", 2, `{ALTCOLOUR}${getGlobalConfig().economy.upKeepCosts.upKeepPerVehicle}{MAINCOLOUR}`, `{ALTCOLOUR}${getGlobalConfig().economy.upKeepCosts.upKeepPerHouse}{MAINCOLOUR}`, `{ALTCOLOUR}${getGlobalConfig().economy.upKeepCosts.upKeepPerBusiness}{MAINCOLOUR}`));
messagePlayerHelpContent(client, getGroupedLocaleString(client, "WealthAndTaxHelp", 2, `{ALTCOLOUR}${getServerConfig().economy.upKeepCosts.upKeepPerVehicle}{MAINCOLOUR}`, `{ALTCOLOUR}${getServerConfig().economy.upKeepCosts.upKeepPerHouse}{MAINCOLOUR}`, `{ALTCOLOUR}${getServerConfig().economy.upKeepCosts.upKeepPerBusiness}{MAINCOLOUR}`));
messagePlayerHelpContent(client, getGroupedLocaleString(client, "WealthAndTaxHelp", 3, `{ALTCOLOUR}/wealth{MAINCOLOUR}`, `{ALTCOLOUR}/tax{MAINCOLOUR}`));
}
// ===========================================================================
function showAdminHelpMessage(client, flagName) {
if (getPlayerData(client).accountData.flags.admin == 0) {
messagePlayerError(client, getLocaleString(client, "CommandNoPermissions", `{ALTCOLOUR}/info admin`));
return false;
}
if (!flagName) {
messagePlayerSyntax(client, `${getCommandSyntaxText("help")} admin <flag name>`);
messagePlayerInfo(client, `Use /staffflags to see a list of staff flags`);
return false;
}
let commandList = getCommandsUsableByStaffFlag(flagName).map(function (x) {
return `/${x.command}`;
});
let chunkedList = splitArrayIntoChunks(commandList, 8);
messagePlayerNormal(client, makeChatBoxSectionHeader(getLocaleString(client, "HeaderCommandsForStaffFlagList", flagName)));
for (let i in chunkedList) {
messagePlayerNormal(client, `{ALTCOLOUR}${chunkedList[i].join(", ")}{MAINCOLOUR}`);
}
}
// ===========================================================================
function showCommandHelpMessage(client, commandName) {
if (!commandName) {
messagePlayerSyntax(client, `${getCommandSyntaxText("help")}command <command name>`);

View File

@@ -213,7 +213,16 @@ function createHouseCommand(command, params, client) {
return false;
}
createHouse(params, getPlayerPosition(client), toVector3(0.0, 0.0, 0.0), getGameConfig().pickupModels[getGame()].House, -1, getPlayerInterior(client), getPlayerDimension(client), getPlayerData(client).interiorScene);
createHouse(
params,
getPlayerPosition(client),
toVector3(0.0, 0.0, 0.0),
(isGameFeatureSupported("pickup")) ? getGameConfig().pickupModels[getGame()].House : -1,
-1,
getPlayerInterior(client),
getPlayerDimension(client),
getPlayerData(client).interiorScene
);
messageAdmins(`{adminOrange}${getPlayerName(client)}{MAINCOLOUR} created house: {houseGreen}${params}`, true);
}
@@ -461,7 +470,7 @@ function setHousePickupCommand(command, params, client) {
getHouseData(houseId).entrancePickupModel = toInteger(typeParam);
}
deleteHouseEntrancePickup(houseId);
despawnHouseEntrancePickup(houseId);
spawnHouseEntrancePickup(houseId);
getHouseData(houseId).needsSaved = true;
@@ -525,8 +534,8 @@ function setHouseInteriorTypeCommand(command, params, client) {
getHouseData(houseId).hasInterior = true;
}
deleteHouseEntrancePickup(houseId);
deleteHouseExitPickup(houseId);
despawnHouseEntrancePickup(houseId);
despawnHouseExitPickup(houseId);
spawnHouseEntrancePickup(houseId);
spawnHouseExitPickup(houseId);
@@ -652,8 +661,8 @@ function moveHouseExitCommand(command, params, client) {
//createAllHouseBlips(houseId);
//createAllHousePickups(houseId);
deleteHouseExitPickup(houseId);
deleteHouseExitBlip(houseId);
despawnHouseExitPickup(houseId);
despawnHouseExitBlip(houseId);
spawnHouseExitPickup(houseId);
spawnHouseExitBlip(houseId);
@@ -714,11 +723,11 @@ function deleteHouse(houseIndex, whoDeleted = 0) {
disconnectFromDatabase(dbConnection);
}
deleteHouseEntrancePickup(houseIndex);
deleteHouseExitPickup(houseIndex);
despawnHouseEntrancePickup(houseIndex);
despawnHouseExitPickup(houseIndex);
deleteHouseEntranceBlip(houseIndex);
deleteHouseExitBlip(houseIndex);
despawnHouseEntranceBlip(houseIndex);
despawnHouseExitBlip(houseIndex);
removePlayersFromHouse(houseIndex);
@@ -1049,35 +1058,45 @@ function spawnHouseEntrancePickup(houseId) {
// return false;
//}
if (houseData.entrancePickupModel == -1) {
return false;
}
logToConsole(LOG_VERBOSE, `[V.RP.House]: Creating entrance pickup for house ${houseData.description} (${houseData.databaseId})`);
if (areServerElementsSupported() && getGame() != V_GAME_MAFIA_ONE && getGame() != V_GAME_GTA_IV) {
let entrancePickup = null;
if (isGameFeatureSupported("pickup")) {
let pickupModelId = getGameConfig().pickupModels[getGame()].House;
if (houseData.entrancePickupModel == -1) {
return false;
}
if (getServerData().houses[houseId].entrancePickupModel != 0) {
pickupModelId = getHouseData(houseId).entrancePickupModel;
}
entrancePickup = createGamePickup(pickupModelId, houseData.entrancePosition, getGameConfig().pickupTypes[getGame()].house);
} else if (isGameFeatureSupported("dummyElement")) {
entrancePickup = createGameDummyElement(houseData.exitPosition);
}
if (entrancePickup != null) {
setElementOnAllDimensions(entrancePickup, false);
setElementDimension(entrancePickup, getHouseData(houseId).entranceDimension);
setElementStreamInDistance(entrancePickup, getGlobalConfig().housePickupStreamInDistance);
setElementStreamOutDistance(entrancePickup, getGlobalConfig().housePickupStreamOutDistance);
setElementTransient(entrancePickup, false);
if (houseData.entranceDimension != -1) {
setElementDimension(entrancePickup, houseData.entranceDimension);
setElementOnAllDimensions(entrancePickup, false);
} else {
setElementOnAllDimensions(entrancePickup, true);
}
if (getGlobalConfig().housePickupStreamInDistance == -1 || getGlobalConfig().housePickupStreamOutDistance == -1) {
entrancePickup.netFlags.distanceStreaming = false;
} else {
setElementStreamInDistance(entrancePickup, getGlobalConfig().housePickupStreamInDistance);
setElementStreamOutDistance(entrancePickup, getGlobalConfig().housePickupStreamInDistance);
}
setElementTransient(entrancePickup, false);
getHouseData(houseId).entrancePickup = entrancePickup;
updateHousePickupLabelData(houseId);
}
}
updateHousePickupLabelData(houseId);
}
// ===========================================================================
@@ -1482,7 +1501,7 @@ function doesHouseHaveInterior(houseId) {
// ===========================================================================
function deleteHouseEntrancePickup(houseId) {
function despawnHouseEntrancePickup(houseId) {
if (!areServerElementsSupported()) {
return false;
}
@@ -1496,7 +1515,7 @@ function deleteHouseEntrancePickup(houseId) {
// ===========================================================================
function deleteHouseExitPickup(houseId) {
function despawnHouseExitPickup(houseId) {
if (!areServerElementsSupported()) {
return false;
}
@@ -1510,7 +1529,7 @@ function deleteHouseExitPickup(houseId) {
// ===========================================================================
function deleteHouseEntranceBlip(houseId) {
function despawnHouseEntranceBlip(houseId) {
if (!areServerElementsSupported()) {
return false;
}
@@ -1524,7 +1543,7 @@ function deleteHouseEntranceBlip(houseId) {
// ===========================================================================
function deleteHouseExitBlip(houseId) {
function despawnHouseExitBlip(houseId) {
if (!areServerElementsSupported()) {
return false;
}
@@ -1556,10 +1575,10 @@ function reloadAllHousesCommand(command, params, client) {
}
for (let i in getServerData().houses) {
deleteHouseExitBlip(i);
deleteHouseEntranceBlip(i);
deleteHouseExitPickup(i);
deleteHouseEntrancePickup(i);
despawnHouseExitBlip(i);
despawnHouseEntranceBlip(i);
despawnHouseExitPickup(i);
despawnHouseEntrancePickup(i);
}
clearArray(getServerData().houses);
@@ -1700,8 +1719,8 @@ function canPlayerLockUnlockHouse(client, houseId) {
// ===========================================================================
function resetHousePickups(houseId) {
deleteHouseEntrancePickup(houseId);
deleteHouseExitPickup(houseId);
despawnHouseEntrancePickup(houseId);
despawnHouseExitPickup(houseId);
spawnHouseEntrancePickup(houseId);
spawnHouseExitPickup(houseId);
}
@@ -1709,8 +1728,8 @@ function resetHousePickups(houseId) {
// ===========================================================================
function resetHouseBlips(houseId) {
deleteHouseEntranceBlip(houseId);
deleteHouseExitBlip(houseId);
despawnHouseEntranceBlip(houseId);
despawnHouseExitBlip(houseId);
spawnHouseEntranceBlip(houseId);
spawnHouseExitBlip(houseId);
}
@@ -1778,13 +1797,17 @@ function getHouseFromParams(params) {
// ===========================================================================
function updateHousePickupLabelData(houseId) {
let houseData = getHouseData(houseId);
if (!areServerElementsSupported() || getGame() == V_GAME_MAFIA_ONE || getGame() == V_GAME_GTA_IV) {
sendHouseToPlayer(null, houseId, getHouseData(houseId).description, getHouseData(houseId).entrancePosition, getHouseEntranceBlipModelForNetworkEvent(houseId), getHouseEntrancePickupModelForNetworkEvent(houseId), getHouseData(houseId).buyPrice, getHouseData(houseId).rentPrice, getHouseData(houseId).hasInterior, getHouseData(houseId).locked);
if (houseData == false) {
sendHouseToPlayer(null, houseId, true, "", false, -1, -1, 0, 0, false, false, false);
} else {
sendHouseToPlayer(null, houseId, false, houseData.description, houseData.entrancePosition, getHouseEntranceBlipModelForNetworkEvent(houseId), getHouseEntrancePickupModelForNetworkEvent(houseId), houseData.buyPrice, houseData.rentPrice, houseData.hasInterior, houseData.locked);
}
return false;
}
let houseData = getHouseData(houseId);
if (houseData.entrancePickup != null) {
setEntityData(houseData.entrancePickup, "v.rp.owner.type", V_PICKUP_HOUSE_ENTRANCE, false);
setEntityData(houseData.entrancePickup, "v.rp.owner.id", houseId, false);
@@ -1813,8 +1836,8 @@ function updateHousePickupLabelData(houseId) {
function deleteAllHouseBlips() {
for (let i in getServerData().houses) {
deleteHouseEntranceBlip(i);
deleteHouseExitBlip(i);
despawnHouseEntranceBlip(i);
despawnHouseExitBlip(i);
}
}
@@ -1822,21 +1845,21 @@ function deleteAllHouseBlips() {
function deleteAllHousePickups() {
for (let i in getServerData().houses) {
deleteHouseEntrancePickup(i);
deleteHouseExitPickup(i);
despawnHouseEntrancePickup(i);
despawnHouseExitPickup(i);
}
}
// ===========================================================================
function createHouseBlips(houseId) {
function spawnHouseBlips(houseId) {
spawnHouseEntranceBlip(houseId);
spawnHouseExitBlip(houseId);
}
// ===========================================================================
function createHousePickups(houseId) {
function spawnHousePickups(houseId) {
spawnHouseEntrancePickup(houseId);
spawnHouseExitPickup(houseId);
}
@@ -1890,4 +1913,49 @@ function getHouseEntrancePickupModelForNetworkEvent(houseIndex) {
return pickupModelId;
}
// ===========================================================================
function getNearbyBusinessesCommand(command, params, client) {
let distance = 10.0;
if (!areParamsEmpty(params)) {
distance = getParam(params, " ", 1);
}
if (isNaN(distance)) {
messagePlayerError(client, "The distance must be a number!");
return false;
}
distance = toFloat(distance);
if (distance <= 0) {
messagePlayerError(client, "The distance must be more than 0!");
return false;
}
let nearbyHouses = getHousesInRange(getPlayerPosition(client), distance);
if (nearbyHouses.length == 0) {
messagePlayerAlert(client, getLocaleString(client, "NoHousesWithinRange", distance));
return false;
}
let housesList = nearbyHouses.map(function (x) {
return `{chatBoxListIndex}${x.index}: {MAINCOLOUR}${x.description} {mediumGrey}(${toFloat(getDistance(getPlayerPosition(client), x.entrancePosition)).toFixed(2)} ${toLowerCase(getLocaleString(client, "Meters"))} ${toLowerCase(getGroupedLocaleString(client, "CardinalDirections", getCardinalDirectionName(getCardinalDirection(getPlayerPosition(client), x.entrancePosition))))})`;
});
let chunkedList = splitArrayIntoChunks(housesList, 4);
messagePlayerNormal(client, makeChatBoxSectionHeader(getLocaleString(client, "HeaderHousesInRangeList", `${distance} ${toLowerCase(getLocaleString(client, "Meters"))}`)));
for (let i in chunkedList) {
messagePlayerInfo(client, chunkedList[i].join(", "));
}
}
// ===========================================================================
function getHousesInRange(position, distance) {
return getServerData().houses.filter((house) => getDistance(position, house.entrancePosition) <= distance);
}
// ===========================================================================

View File

@@ -347,6 +347,8 @@ function createItem(itemTypeId, value, ownerType, ownerId, amount = 1) {
let index = slot - 1;
getServerData().items[slot - 1].index = index;
getServerData().items[slot - 1].itemTypeIndex = itemTypeId;
saveItemToDatabase(slot - 1);
return index;
}
@@ -828,7 +830,7 @@ function createItemTypeCommand(command, params, client) {
}
let itemTypeIndex = createItemType(params);
messageAdmins(`{ALTCOLOUR}${getPlayerName(client)} created new item type: {ALTCOLOUR}${params}. {MAINCOLOUR}ID: ${itemTypeIndex}/${getItemTypeData(itemTypeIndex).databaseId}!`, true);
messageAdmins(`{ALTCOLOUR}${getPlayerName(client)}{MAINCOLOUR} created new item type: {ALTCOLOUR}${params}. {MAINCOLOUR}ID: ${itemTypeIndex}/${getItemTypeData(itemTypeIndex).databaseId}!`, true);
}
// ===========================================================================
@@ -857,9 +859,14 @@ function setItemTypeDropModelCommand(command, params, client) {
return false;
}
if (isNaN(orderPrice)) {
messagePlayerError(client, `The model index must be a number!`);
return false;
}
getItemTypeData(itemTypeIndex).dropModel = modelIndex;
getItemTypeData(itemTypeIndex).needsSaved = true;
messageAdmins(`{ALTCOLOUR}${getPlayerName(client)} set item type {ALTCOLOUR}${getItemTypeData(itemTypeIndex).name}'s{MAINCOLOUR} dropped object model index to ${modelIndex}`, true);
messageAdmins(`{ALTCOLOUR}${getPlayerName(client)}{MAINCOLOUR} set item type {ALTCOLOUR}${getItemTypeData(itemTypeIndex).name}'s{MAINCOLOUR} dropped object model index to ${modelIndex}`, true);
}
// ===========================================================================
@@ -888,9 +895,14 @@ function setItemTypeOrderPriceCommand(command, params, client) {
return false;
}
if (isNaN(orderPrice)) {
messagePlayerError(client, `The order price must be a number!`);
return false;
}
getItemTypeData(itemTypeIndex).orderPrice = orderPrice;
getItemTypeData(itemTypeIndex).needsSaved = true;
messageAdmins(`{ALTCOLOUR}${getPlayerName(client)} set item type {ALTCOLOUR}${getItemTypeData(itemTypeIndex).name}{MAINCOLOUR} base price to {ALTCOLOUR}${getCurrencyString(orderPrice)}`, true);
messageAdmins(`{ALTCOLOUR}${getPlayerName(client)}{MAINCOLOUR} set item type {ALTCOLOUR}${getItemTypeData(itemTypeIndex).name}{MAINCOLOUR} base price to {ALTCOLOUR}${getCurrencyString(orderPrice)}`, true);
}
// ===========================================================================
@@ -919,9 +931,14 @@ function setItemTypeOrderValueCommand(command, params, client) {
return false;
}
if (isNaN(orderValue)) {
messagePlayerError(client, `The order value must be a number!`);
return false;
}
getItemTypeData(itemTypeIndex).orderValue = orderValue;
getItemTypeData(itemTypeIndex).needsSaved = true;
messageAdmins(`{ALTCOLOUR}${getPlayerName(client)} set item type {ALTCOLOUR}${getItemTypeData(itemTypeIndex).name}{MAINCOLOUR} order value to {ALTCOLOUR}${orderValue}`, true);
messageAdmins(`{ALTCOLOUR}${getPlayerName(client)}{MAINCOLOUR} set item type {ALTCOLOUR}${getItemTypeData(itemTypeIndex).name}{MAINCOLOUR} order value to {ALTCOLOUR}${orderValue}`, true);
}
// ===========================================================================
@@ -950,9 +967,14 @@ function setItemTypeRiskMultiplierCommand(command, params, client) {
return false;
}
if (isNaN(riskMultiplier)) {
messagePlayerError(client, `The risk multiplier must be a number!`);
return false;
}
getItemTypeData(itemTypeIndex).riskMultiplier = riskMultiplier / 100;
getItemTypeData(itemTypeIndex).needsSaved = true;
messageAdmins(`{ALTCOLOUR}${getPlayerName(client)} set item type {ALTCOLOUR}${getItemTypeData(itemTypeIndex).name}{MAINCOLOUR} risk multiplier to {ALTCOLOUR}${riskMultiplier}%`, true);
messageAdmins(`{ALTCOLOUR}${getPlayerName(client)}{MAINCOLOUR} set item type {ALTCOLOUR}${getItemTypeData(itemTypeIndex).name}{MAINCOLOUR} risk multiplier to {ALTCOLOUR}${riskMultiplier}%`, true);
}
// ===========================================================================
@@ -981,7 +1003,7 @@ function toggleItemTypeEnabledCommand(command, params, client) {
getItemTypeData(itemTypeIndex).enabled = !getItemTypeData(itemTypeIndex).enabled;
getItemTypeData(itemTypeIndex).needsSaved = true;
messageAdmins(`{ALTCOLOUR}${getPlayerName(client)} ${getEnabledDisabledFromBool(getItemTypeData(itemTypeIndex).enabled)} item type {ALTCOLOUR}${getItemTypeData(itemTypeIndex).name}`, true);
messageAdmins(`{ALTCOLOUR}${getPlayerName(client)}{MAINCOLOUR} ${getEnabledDisabledFromBool(getItemTypeData(itemTypeIndex).enabled)} item type {ALTCOLOUR}${getItemTypeData(itemTypeIndex).name}`, true);
}
// ===========================================================================
@@ -1010,9 +1032,14 @@ function setItemTypeUseTypeCommand(command, params, client) {
return false;
}
if (isNaN(useType)) {
messagePlayerError(client, `The use type must be a number!`);
return false;
}
getItemTypeData(itemTypeIndex).useType = useType;
getItemTypeData(itemTypeIndex).needsSaved = true;
messageAdmins(`{ALTCOLOUR}${getPlayerName(client)} set item type {ALTCOLOUR}${getItemTypeData(itemTypeIndex).name}{MAINCOLOUR} use type to {ALTCOLOUR}${useType}`, true);
messageAdmins(`{ALTCOLOUR}${getPlayerName(client)}{MAINCOLOUR} set item type {ALTCOLOUR}${getItemTypeData(itemTypeIndex).name}{MAINCOLOUR} use type to {ALTCOLOUR}${useType}`, true);
}
// ===========================================================================
@@ -1043,7 +1070,7 @@ function setItemTypeUseValueCommand(command, params, client) {
getItemTypeData(itemTypeIndex).useValue = useValue;
getItemTypeData(itemTypeIndex).needsSaved = true;
messageAdmins(`{ALTCOLOUR}${getPlayerName(client)} set item type {ALTCOLOUR}${getItemTypeData(itemTypeIndex).name}{MAINCOLOUR} use value to {ALTCOLOUR}${useValue}`, true);
messageAdmins(`{ALTCOLOUR}${getPlayerName(client)}{MAINCOLOUR} set item type {ALTCOLOUR}${getItemTypeData(itemTypeIndex).name}{MAINCOLOUR} use value to {ALTCOLOUR}${useValue}`, true);
}
// ===========================================================================
@@ -1073,13 +1100,13 @@ function setItemTypeDropFrontDistanceCommand(command, params, client) {
}
if (isNaN(dropFrontDistance)) {
messagePlayerError(client, `The distance must be a number!`);
messagePlayerError(client, `The front distance must be a number!`);
return false;
}
getItemTypeData(itemTypeIndex).dropFrontDistance = dropFrontDistance;
getItemTypeData(itemTypeIndex).needsSaved = true;
messageAdmins(`{ALTCOLOUR}${getPlayerName(client)} set item type {ALTCOLOUR}${getItemTypeData(itemTypeIndex).name}{MAINCOLOUR} drop front distance to {ALTCOLOUR}${dropFrontDistance.toFixed(2)}`, true);
messageAdmins(`{ALTCOLOUR}${getPlayerName(client)}{MAINCOLOUR} set item type {ALTCOLOUR}${getItemTypeData(itemTypeIndex).name}{MAINCOLOUR} drop front distance to {ALTCOLOUR}${dropFrontDistance.toFixed(2)}`, true);
}
// ===========================================================================
@@ -1119,7 +1146,7 @@ function setItemTypeDropPositionCommand(command, params, client) {
getItemTypeData(itemTypeIndex).dropPosition = dropPosition;
getItemTypeData(itemTypeIndex).needsSaved = true;
messageAdmins(`{ALTCOLOUR}${getPlayerName(client)} set item type {ALTCOLOUR}${getItemTypeData(itemTypeIndex).name}{MAINCOLOUR} drop position offset to {ALTCOLOUR}${dropPosition.x.toFixed(2)}, ${dropPosition.y.toFixed(2)}, ${dropPosition.z.toFixed(2)}`, true);
messageAdmins(`{ALTCOLOUR}${getPlayerName(client)}{MAINCOLOUR} set item type {ALTCOLOUR}${getItemTypeData(itemTypeIndex).name}{MAINCOLOUR} drop position offset to {ALTCOLOUR}${dropPosition.x.toFixed(2)}, ${dropPosition.y.toFixed(2)}, ${dropPosition.z.toFixed(2)}`, true);
}
// ===========================================================================
@@ -1151,7 +1178,7 @@ function setItemTypeDropRotationCommand(command, params, client) {
}
if (isNaN(x) || isNaN(y) || isNaN(z)) {
messagePlayerError(client, `The positions must be numbers!`);
messagePlayerError(client, `The rotation values must be numbers!`);
return false;
}
@@ -1159,7 +1186,7 @@ function setItemTypeDropRotationCommand(command, params, client) {
getItemTypeData(itemTypeIndex).dropRotation = dropRotation;
getItemTypeData(itemTypeIndex).needsSaved = true;
messageAdmins(`{ALTCOLOUR}${getPlayerName(client)} set item type {ALTCOLOUR}${getItemTypeData(itemTypeIndex).name}{MAINCOLOUR} drop rotation to {ALTCOLOUR}${dropRotation.x.toFixed(2)}, ${dropRotation.y.toFixed(2)}, ${dropRotation.z.toFixed(2)}`, true);
messageAdmins(`{ALTCOLOUR}${getPlayerName(client)}{MAINCOLOUR} set item type {ALTCOLOUR}${getItemTypeData(itemTypeIndex).name}{MAINCOLOUR} drop rotation to {ALTCOLOUR}${dropRotation.x.toFixed(2)}, ${dropRotation.y.toFixed(2)}, ${dropRotation.z.toFixed(2)}`, true);
}
// ===========================================================================
@@ -1191,7 +1218,7 @@ function setItemTypeDropScaleCommand(command, params, client) {
}
if (isNaN(x) || isNaN(y) || isNaN(z)) {
messagePlayerError(client, `The positions must be numbers!`);
messagePlayerError(client, `The scale values must be numbers!`);
return false;
}
@@ -1199,7 +1226,7 @@ function setItemTypeDropScaleCommand(command, params, client) {
getItemTypeData(itemTypeIndex).dropScale = dropScale;
getItemTypeData(itemTypeIndex).needsSaved = true;
messageAdmins(`{ALTCOLOUR}${getPlayerName(client)} set item type {ALTCOLOUR}${getItemTypeData(itemTypeIndex).name}{MAINCOLOUR} drop scale to {ALTCOLOUR}${dropScale.x.toFixed(2)}, ${dropScale.y.toFixed(2)}, ${dropScale.z.toFixed(2)}`, true);
messageAdmins(`{ALTCOLOUR}${getPlayerName(client)}{MAINCOLOUR} set item type {ALTCOLOUR}${getItemTypeData(itemTypeIndex).name}{MAINCOLOUR} drop scale to {ALTCOLOUR}${dropScale.x.toFixed(2)}, ${dropScale.y.toFixed(2)}, ${dropScale.z.toFixed(2)}`, true);
}
// ===========================================================================
@@ -1235,7 +1262,7 @@ function setItemTypeDemandMultiplierCommand(command, params, client) {
getItemTypeData(itemTypeIndex).demandMultiplier = demandMultiplier / 100;
getItemTypeData(itemTypeIndex).needsSaved = true;
messageAdmins(`{ALTCOLOUR}${getPlayerName(client)} set item type {ALTCOLOUR}${getItemTypeData(itemTypeIndex).name}{MAINCOLOUR} demand multiplier to {ALTCOLOUR}${demandMultiplier}%`, true);
messageAdmins(`{ALTCOLOUR}${getPlayerName(client)}{MAINCOLOUR} set item type {ALTCOLOUR}${getItemTypeData(itemTypeIndex).name}{MAINCOLOUR} demand multiplier to {ALTCOLOUR}${demandMultiplier}%`, true);
}
// ===========================================================================
@@ -1271,7 +1298,7 @@ function setItemTypeMaxValueCommand(command, params, client) {
getItemTypeData(itemTypeIndex).maxValue = maxValue;
getItemTypeData(itemTypeIndex).needsSaved = true;
messageAdmins(`{ALTCOLOUR}${getPlayerName(client)} set item type {ALTCOLOUR}${getItemTypeData(itemTypeIndex).name}{MAINCOLOUR} max value to {ALTCOLOUR}${maxValue}`, true);
messageAdmins(`{ALTCOLOUR}${getPlayerName(client)}{MAINCOLOUR} set item type {ALTCOLOUR}${getItemTypeData(itemTypeIndex).name}{MAINCOLOUR} max value to {ALTCOLOUR}${maxValue}`, true);
}
// ===========================================================================
@@ -1307,7 +1334,7 @@ function setItemTypeSizeCommand(command, params, client) {
getItemTypeData(itemTypeIndex).size = size;
getItemTypeData(itemTypeIndex).needsSaved = true;
messageAdmins(`{ALTCOLOUR}${getPlayerName(client)} set item type {ALTCOLOUR}${getItemTypeData(itemTypeIndex).name}{MAINCOLOUR} size to {ALTCOLOUR}${size}`, true);
messageAdmins(`{ALTCOLOUR}${getPlayerName(client)}{MAINCOLOUR} set item type {ALTCOLOUR}${getItemTypeData(itemTypeIndex).name}{MAINCOLOUR} size to {ALTCOLOUR}${size}`, true);
}
// ===========================================================================
@@ -1343,7 +1370,7 @@ function setItemTypeCapacityCommand(command, params, client) {
getItemTypeData(itemTypeIndex).capacity = capacity;
getItemTypeData(itemTypeIndex).needsSaved = true;
messageAdmins(`{ALTCOLOUR}${getPlayerName(client)} set item type {ALTCOLOUR}${getItemTypeData(itemTypeIndex).name}{MAINCOLOUR} capacity to {ALTCOLOUR}${capacity}`, true);
messageAdmins(`{ALTCOLOUR}${getPlayerName(client)}{MAINCOLOUR} set item type {ALTCOLOUR}${getItemTypeData(itemTypeIndex).name}{MAINCOLOUR} capacity to {ALTCOLOUR}${capacity}`, true);
}
// ===========================================================================
@@ -1518,13 +1545,13 @@ function playerUseItem(client, hotBarSlot) {
itemData.value = itemData.value - itemTypeData.useValue;
if (itemData.value <= 0) {
destroyItem(itemIndex);
deleteItem(itemIndex);
}
markPlayerActionTipSeen(client, "VehicleRepairItemUsage");
} else {
messagePlayerError(client, getLocaleString(client, "VehicleTooFar"));
}
markPlayerActionTipSeen(client, "VehicleRepairItemUsage");
break;
}
@@ -1583,7 +1610,7 @@ function playerUseItem(client, hotBarSlot) {
itemData.value = itemData.value - itemTypeData.useValue;
//if(itemData.value <= 0) {
// destroyItem(itemIndex);
// deleteItem(itemIndex);
//}
}
} else {
@@ -1644,6 +1671,7 @@ function playerUseItem(client, hotBarSlot) {
if (getPlayerData(client).incomingDamageMultiplier < 0.25) {
getPlayerData(client).incomingDamageMultiplier = 0.25;
}
sendIncomingDamageMultiplierToClient(client, getPlayerData(client).incomingDamageMultiplier);
deleteItem(itemIndex);
switchPlayerActiveHotBarSlot(client, -1);
break;
@@ -1655,6 +1683,7 @@ function playerUseItem(client, hotBarSlot) {
if (getPlayerData(client).incomingDamageMultiplier < 0.25) {
getPlayerData(client).incomingDamageMultiplier = 0.25;
}
sendIncomingDamageMultiplierToClient(client, getPlayerData(client).incomingDamageMultiplier);
deleteItem(itemIndex);
switchPlayerActiveHotBarSlot(client, -1);
break;
@@ -1666,6 +1695,7 @@ function playerUseItem(client, hotBarSlot) {
if (getPlayerData(client).incomingDamageMultiplier < 0.25) {
getPlayerData(client).incomingDamageMultiplier = 0.25;
}
sendIncomingDamageMultiplierToClient(client, getPlayerData(client).incomingDamageMultiplier);
deleteItem(itemIndex);
switchPlayerActiveHotBarSlot(client, -1);
break;
@@ -1675,7 +1705,7 @@ function playerUseItem(client, hotBarSlot) {
meActionToNearbyPlayers(client, `bends down and plants a ${itemTypeData.name} in the ground`);
createGroundPlant(itemIndex);
if (itemData.value == 0) {
destroyItem(itemIndex);
deleteItem(itemIndex);
switchPlayerActiveHotBarSlot(client, -1);
}
break;
@@ -1767,14 +1797,18 @@ function playerDropItem(client, hotBarSlot) {
updatePlayerHotBar(client);
clearPlayerWeapons(client);
let position = getPosInFrontOfPos(getPlayerPosition(client), getPlayerHeading(client), getItemTypeData(getItemData(itemId).itemTypeIndex).dropFrontDistance);
getItemData(itemId).ownerType = V_ITEM_OWNER_GROUND;
getItemData(itemId).ownerId = 0;
getItemData(itemId).position = getPosInFrontOfPos(getPlayerPosition(client), getPlayerHeading(client), getItemTypeData(getItemData(itemId).itemTypeIndex).dropFrontDistance);
getItemData(itemId).position = position;
getItemData(itemId).dimension = getPlayerDimension(client);
//getItemData(itemId).interior = getPlayerInterior(client);
spawnGroundItemObject(itemId);
getItemData(itemId).needsSaved = true;
getServerData().groundItemCache.push(itemId);
logItemMove(getItemData(itemId).databaseId, V_ITEM_OWNER_PLAYER, getPlayerCurrentSubAccount(client).databaseId, V_ITEM_OWNER_GROUND, 0, position);
}
}
@@ -1854,6 +1888,8 @@ function playerPickupItem(client, itemId) {
getPlayerData(client).hotBarItems[firstSlot] = itemId;
updatePlayerHotBar(client);
logItemMove(getItemData(itemId).databaseId, V_ITEM_OWNER_GROUND, 0, V_ITEM_OWNER_PLAYER, getPlayerCurrentSubAccount(client).databaseId, position);
}
}
@@ -2378,6 +2414,8 @@ function listPlayerInventoryCommand(command, params, client) {
//showPlayerInventoryToPlayer(client, targetClient);
showPlayerInventoryToPlayer(client, client);
markPlayerActionTipSeen(client, "ViewInventory");
}
// ===========================================================================
@@ -3304,4 +3342,14 @@ function despawnAllGroundItemObjects() {
}
}
// ===========================================================================
function logItemMove(itemId, fromType, fromId, toType, toId, position = toVector3(0.0, 0.0, 0.0)) {
if (getServerConfig().devServer) {
return false;
}
quickDatabaseQuery(`INSERT INTO log_item_move (log_item_move_item, log_item_move_from_type, log_item_move_from_id, log_item_move_to_type, log_item_move_to_id, log_item_move_when, log_item_move_pos_x, log_item_move_pos_y, log_item_move_pos_z) VALUES (${itemId}, ${fromType}, ${fromId}, ${toType}, ${toId}, UNIX_TIMESTAMP(), ${position.x}, ${position.y}, ${position.z})`);
}
// ===========================================================================

View File

@@ -44,13 +44,6 @@ const V_JOB_ROUTE_LOC_TYPE_FIRE = 5; // Scripted fire, placed on build
/**
* @class Representing a job's data. Loaded and saved in the database
* @property {Array.<JobEquipmentData>} equipment
* @property {Array.<JobUniformData>} uniforms
* @property {Array.<JobLocationData>} locations
* @property {Array.<JobRouteData>} routes
* @property {Array.<JobWhiteListData>} whiteList
* @property {Array.<JobBlackListData>} blackList
* @property {Array.<JobRankData>} ranks
*/
class JobData {
constructor(dbAssoc = false) {
@@ -70,12 +63,25 @@ class JobData {
this.whoCreated = 0;
this.whenCreated = 0;
/** @type {Array.<JobEquipmentData>} */
this.equipment = [];
/** @type {Array.<JobUniformData>} */
this.uniforms = [];
/** @type {Array.<JobLocationData>} */
this.locations = [];
/** @type {Array.<JobWhiteListData>} */
this.whiteList = [];
/** @type {Array.<JobBlackListData>} */
this.blackList = [];
/** @type {Array.<JobRouteData>} */
this.routes = [];
/** @type {Array.<JobRankData>} */
this.ranks = [];
if (dbAssoc) {
@@ -130,11 +136,13 @@ class JobRouteData {
//this.failedMessage = "";
this.locationArriveMessage = "";
this.locationGotoMessage = "";
this.locations = [];
this.whoCreated = 0;
this.whenCreated = 0;
this.sphere = null;
/** @type {Array.<JobRouteLocationData>} */
this.locations = [];
if (dbAssoc) {
this.databaseId = toInteger(dbAssoc["job_route_id"]);
this.name = toString(dbAssoc["job_route_name"]);
@@ -213,10 +221,12 @@ class JobEquipmentData {
this.index = -1;
this.jobIndex = -1;
this.needsSaved = false;
this.items = [];
this.whoCreated = 0;
this.whenCreated = 0;
/** @type {Array.<JobEquipmentItemData>} */
this.items = [];
if (dbAssoc) {
this.databaseId = dbAssoc["job_equip_id"];
this.job = dbAssoc["job_equip_job"];
@@ -391,6 +401,7 @@ class JobRankData {
this.whenCreated = 0;
this.flags = 0;
this.needsSaved = false;
this.public = false;
if (dbAssoc) {
this.databaseId = toInteger(dbAssoc["job_rank_id"]);
@@ -402,6 +413,7 @@ class JobRankData {
this.whoCreated = toInteger(dbAssoc["job_rank_who_added"]);
this.whenCreated = toInteger(dbAssoc["job_rank_when_added"]);
this.flags = toInteger(dbAssoc["job_rank_flags"]);
this.public = intToBool(dbAssoc["job_rank_public"]);
}
}
};
@@ -458,7 +470,7 @@ class JobBlackListData {
// ===========================================================================
class JobRouteLocationType {
class JobRouteLocationTypeData {
constructor(jobRouteLocationTypeId, name, animStart = "", animStop = "", inVehicle = false, nearVehicle = false, nearVehicleDistance = 5.0) {
}
@@ -469,59 +481,59 @@ class JobRouteLocationType {
// For use with the /jobrouteloctype command
let jobRouteLocationTypes = {
[V_GAME_GTA_III]: [
new JobRouteLocationType(V_JOB_ROUTE_LOC_TYPE_CHECKPOINT, "Checkpoint"),
new JobRouteLocationType(V_JOB_ROUTE_LOC_TYPE_GROUND_GARBAGE, "GroundGarbage"),
new JobRouteLocationType(V_JOB_ROUTE_LOC_TYPE_GARBAGE_BIN, "GarbagePickup"),
new JobRouteLocationType(V_JOB_ROUTE_LOC_TYPE_BURNING_VEHICLE, "BurningVehicle"),
new JobRouteLocationType(V_JOB_ROUTE_LOC_TYPE_INJURED_PED, "InjuredPed"),
new JobRouteLocationTypeData(V_JOB_ROUTE_LOC_TYPE_CHECKPOINT, "Checkpoint"),
new JobRouteLocationTypeData(V_JOB_ROUTE_LOC_TYPE_GROUND_GARBAGE, "GroundGarbage"),
new JobRouteLocationTypeData(V_JOB_ROUTE_LOC_TYPE_GARBAGE_BIN, "GarbagePickup"),
new JobRouteLocationTypeData(V_JOB_ROUTE_LOC_TYPE_BURNING_VEHICLE, "BurningVehicle"),
new JobRouteLocationTypeData(V_JOB_ROUTE_LOC_TYPE_INJURED_PED, "InjuredPed"),
],
[V_GAME_GTA_VC]: [
new JobRouteLocationType(V_JOB_ROUTE_LOC_TYPE_CHECKPOINT, "Checkpoint"),
new JobRouteLocationType(V_JOB_ROUTE_LOC_TYPE_GROUND_GARBAGE, "GroundGarbage"),
new JobRouteLocationType(V_JOB_ROUTE_LOC_TYPE_GARBAGE_BIN, "GarbagePickup"),
new JobRouteLocationType(V_JOB_ROUTE_LOC_TYPE_BURNING_VEHICLE, "BurningVehicle"),
new JobRouteLocationType(V_JOB_ROUTE_LOC_TYPE_INJURED_PED, "InjuredPed"),
new JobRouteLocationTypeData(V_JOB_ROUTE_LOC_TYPE_CHECKPOINT, "Checkpoint"),
new JobRouteLocationTypeData(V_JOB_ROUTE_LOC_TYPE_GROUND_GARBAGE, "GroundGarbage"),
new JobRouteLocationTypeData(V_JOB_ROUTE_LOC_TYPE_GARBAGE_BIN, "GarbagePickup"),
new JobRouteLocationTypeData(V_JOB_ROUTE_LOC_TYPE_BURNING_VEHICLE, "BurningVehicle"),
new JobRouteLocationTypeData(V_JOB_ROUTE_LOC_TYPE_INJURED_PED, "InjuredPed"),
],
[V_GAME_GTA_SA]: [
new JobRouteLocationType(V_JOB_ROUTE_LOC_TYPE_CHECKPOINT, "Checkpoint"),
new JobRouteLocationType(V_JOB_ROUTE_LOC_TYPE_GROUND_GARBAGE, "GroundGarbage"),
new JobRouteLocationType(V_JOB_ROUTE_LOC_TYPE_GARBAGE_BIN, "GarbagePickup"),
new JobRouteLocationType(V_JOB_ROUTE_LOC_TYPE_BURNING_VEHICLE, "BurningVehicle"),
new JobRouteLocationType(V_JOB_ROUTE_LOC_TYPE_INJURED_PED, "InjuredPed"),
new JobRouteLocationTypeData(V_JOB_ROUTE_LOC_TYPE_CHECKPOINT, "Checkpoint"),
new JobRouteLocationTypeData(V_JOB_ROUTE_LOC_TYPE_GROUND_GARBAGE, "GroundGarbage"),
new JobRouteLocationTypeData(V_JOB_ROUTE_LOC_TYPE_GARBAGE_BIN, "GarbagePickup"),
new JobRouteLocationTypeData(V_JOB_ROUTE_LOC_TYPE_BURNING_VEHICLE, "BurningVehicle"),
new JobRouteLocationTypeData(V_JOB_ROUTE_LOC_TYPE_INJURED_PED, "InjuredPed"),
],
[V_GAME_GTA_IV]: [
new JobRouteLocationType(V_JOB_ROUTE_LOC_TYPE_CHECKPOINT, "Checkpoint"),
new JobRouteLocationType(V_JOB_ROUTE_LOC_TYPE_GROUND_GARBAGE, "GroundGarbage"),
new JobRouteLocationType(V_JOB_ROUTE_LOC_TYPE_GARBAGE_BIN, "GarbagePickup"),
new JobRouteLocationType(V_JOB_ROUTE_LOC_TYPE_BURNING_VEHICLE, "BurningVehicle"),
new JobRouteLocationType(V_JOB_ROUTE_LOC_TYPE_INJURED_PED, "InjuredPed"),
new JobRouteLocationTypeData(V_JOB_ROUTE_LOC_TYPE_CHECKPOINT, "Checkpoint"),
new JobRouteLocationTypeData(V_JOB_ROUTE_LOC_TYPE_GROUND_GARBAGE, "GroundGarbage"),
new JobRouteLocationTypeData(V_JOB_ROUTE_LOC_TYPE_GARBAGE_BIN, "GarbagePickup"),
new JobRouteLocationTypeData(V_JOB_ROUTE_LOC_TYPE_BURNING_VEHICLE, "BurningVehicle"),
new JobRouteLocationTypeData(V_JOB_ROUTE_LOC_TYPE_INJURED_PED, "InjuredPed"),
],
[V_GAME_MAFIA_ONE]: [
new JobRouteLocationType(V_JOB_ROUTE_LOC_TYPE_CHECKPOINT, "Checkpoint"),
new JobRouteLocationType(V_JOB_ROUTE_LOC_TYPE_GROUND_GARBAGE, "GroundGarbage"),
new JobRouteLocationType(V_JOB_ROUTE_LOC_TYPE_GARBAGE_BIN, "GarbagePickup"),
new JobRouteLocationType(V_JOB_ROUTE_LOC_TYPE_BURNING_VEHICLE, "BurningVehicle"),
new JobRouteLocationType(V_JOB_ROUTE_LOC_TYPE_INJURED_PED, "InjuredPed"),
new JobRouteLocationTypeData(V_JOB_ROUTE_LOC_TYPE_CHECKPOINT, "Checkpoint"),
new JobRouteLocationTypeData(V_JOB_ROUTE_LOC_TYPE_GROUND_GARBAGE, "GroundGarbage"),
new JobRouteLocationTypeData(V_JOB_ROUTE_LOC_TYPE_GARBAGE_BIN, "GarbagePickup"),
new JobRouteLocationTypeData(V_JOB_ROUTE_LOC_TYPE_BURNING_VEHICLE, "BurningVehicle"),
new JobRouteLocationTypeData(V_JOB_ROUTE_LOC_TYPE_INJURED_PED, "InjuredPed"),
],
[V_GAME_MAFIA_TWO]: [
new JobRouteLocationType(V_JOB_ROUTE_LOC_TYPE_CHECKPOINT, "Checkpoint"),
new JobRouteLocationType(V_JOB_ROUTE_LOC_TYPE_GROUND_GARBAGE, "GroundGarbage"),
new JobRouteLocationType(V_JOB_ROUTE_LOC_TYPE_GARBAGE_BIN, "GarbagePickup"),
new JobRouteLocationType(V_JOB_ROUTE_LOC_TYPE_BURNING_VEHICLE, "BurningVehicle"),
new JobRouteLocationType(V_JOB_ROUTE_LOC_TYPE_INJURED_PED, "InjuredPed"),
new JobRouteLocationTypeData(V_JOB_ROUTE_LOC_TYPE_CHECKPOINT, "Checkpoint"),
new JobRouteLocationTypeData(V_JOB_ROUTE_LOC_TYPE_GROUND_GARBAGE, "GroundGarbage"),
new JobRouteLocationTypeData(V_JOB_ROUTE_LOC_TYPE_GARBAGE_BIN, "GarbagePickup"),
new JobRouteLocationTypeData(V_JOB_ROUTE_LOC_TYPE_BURNING_VEHICLE, "BurningVehicle"),
new JobRouteLocationTypeData(V_JOB_ROUTE_LOC_TYPE_INJURED_PED, "InjuredPed"),
],
[V_GAME_MAFIA_ONE_DE]: [
new JobRouteLocationType(V_JOB_ROUTE_LOC_TYPE_CHECKPOINT, "Checkpoint"),
new JobRouteLocationType(V_JOB_ROUTE_LOC_TYPE_GROUND_GARBAGE, "GroundGarbage"),
new JobRouteLocationType(V_JOB_ROUTE_LOC_TYPE_GARBAGE_BIN, "GarbagePickup"),
new JobRouteLocationType(V_JOB_ROUTE_LOC_TYPE_BURNING_VEHICLE, "BurningVehicle"),
new JobRouteLocationType(V_JOB_ROUTE_LOC_TYPE_INJURED_PED, "InjuredPed"),
new JobRouteLocationTypeData(V_JOB_ROUTE_LOC_TYPE_CHECKPOINT, "Checkpoint"),
new JobRouteLocationTypeData(V_JOB_ROUTE_LOC_TYPE_GROUND_GARBAGE, "GroundGarbage"),
new JobRouteLocationTypeData(V_JOB_ROUTE_LOC_TYPE_GARBAGE_BIN, "GarbagePickup"),
new JobRouteLocationTypeData(V_JOB_ROUTE_LOC_TYPE_BURNING_VEHICLE, "BurningVehicle"),
new JobRouteLocationTypeData(V_JOB_ROUTE_LOC_TYPE_INJURED_PED, "InjuredPed"),
],
}
@@ -1184,7 +1196,7 @@ function stopWorking(client) {
setPlayerSkin(client, getPlayerCurrentSubAccount(client).skin);
deleteJobItems(client);
restorePlayerTempLockerItems(client);
respawnJobVehicle(client);
//respawnJobVehicle(client);
sendPlayerStopJobRoute(client);
let jobId = getPlayerJob(client);
@@ -1303,7 +1315,7 @@ function jobUniformCommand(command, params, client) {
let uniformList = jobData.uniforms.map(function (x) { return `{MAINCOLOUR}${toInteger(x.index) + 1}: {ALTCOLOUR}${x.name}` });
let chunkedList = splitArrayIntoChunks(uniformList, 4);
messagePlayerNormal(client, makeChatBoxSectionHeader(getLocaleString(client, "HeaderJobUniformList")));
messagePlayerNormal(client, makeChatBoxSectionHeader(getLocaleString(client, "HeaderJobUniformList", jobData.name)));
for (let i in chunkedList) {
messagePlayerInfo(client, chunkedList[i].join(", "));
}
@@ -1523,7 +1535,7 @@ function quitJob(client) {
getPlayerCurrentSubAccount(client).jobRank = 0;
getPlayerCurrentSubAccount(client).jobIndex = -1;
getPlayerCurrentSubAccount(client).jobRankIndex = -1;
sendPlayerJobType(client, 0);
sendPlayerJobType(client, -1);
updateJobBlipsForPlayer(client);
}
@@ -1540,7 +1552,7 @@ function takeJob(client, jobId) {
getPlayerCurrentSubAccount(client).jobRank = rankId;
getPlayerCurrentSubAccount(client).jobIndex = jobId;
getPlayerCurrentSubAccount(client).jobRankIndex = rankIndex;
sendPlayerJobType(client, getJobData(jobId).databaseId);
sendPlayerJobType(client, jobId);
updateJobBlipsForPlayer(client);
}
@@ -1553,11 +1565,11 @@ function reloadAllJobsCommand(command, params, client) {
deleteAllJobPickups();
clearArray(getServerData().jobs);
Promise.resolve().then(() => {
getServerData().jobs = loadJobsFromDatabase();
spawnAllJobPickups();
spawnAllJobBlips();
});
//Promise.resolve().then(() => {
getServerData().jobs = loadJobsFromDatabase();
spawnAllJobPickups();
spawnAllJobBlips();
//});
announceAdminAction("AllJobsReloaded");
}
@@ -1618,7 +1630,7 @@ function createJobLocationCommand(command, params, client) {
function deleteJobLocationCommand(command, params, client) {
let closestJobLocation = getClosestJobLocation(getPlayerPosition(client), getPlayerDimension(client));
deleteJobLocation(closestJobLocation.jobIndex, closestJobLocation.index);
deleteJobLocation(closestJobLocation.jobIndex, closestJobLocation.index, getPlayerData(client).accountData.databaseId);
messageAdmins(`{adminOrange}${getPlayerName(client)}{MAINCOLOUR} deleted location {ALTCOLOUR}${closestJobLocation.index} (DB ID ${closestJobLocation.databaseId}){MAINCOLOUR} for the {jobYellow}${getJobData(closestJobLocation.jobIndex).name}{MAINCOLOUR} job`);
}
@@ -1787,6 +1799,46 @@ function setJobPickupCommand(command, params, client) {
// ===========================================================================
function setPlayerJobRankCommand(command, params, client) {
if (areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
let jobIndex = getPlayerJob(client);
if (getJobData(jobIndex) == false) {
messagePlayerError(client, getLocaleString(client, "InvalidJob"));
return false;
}
if (!doesPlayerHaveJobPermission(client, getJobFlagValue("SetRank"))) {
messagePlayerError(client, getLocaleString(client, "JobRankTooLow"));
return false;
}
let targetClient = getPlayerFromParams(getParam(params, " ", 1));
let rankIndex = getJobRankFromParams(jobIndex, params.split(" ").slice(2).join(" "));
if (!targetClient) {
messagePlayerError(client, getLocaleString(client, "InvalidPlayer"));
return false;
}
if (rankIndex == -1) {
messagePlayerError(client, getLocaleString(client, "InvalidJobRank"));
return false;
}
getPlayerCurrentSubAccount(targetClient).jobRankIndex = rankIndex;
getPlayerCurrentSubAccount(targetClient).jobRank = getJobRankData(jobIndex, rankIndex).databaseId;
messagePlayerSuccess(client, `You set {ALTCOLOUR}${getCharacterFullName(targetClient)}'s{MAINCOLOUR} job rank to {ALTCOLOUR}${getJobRankData(jobIndex, rankIndex).name} (level ${getJobRankData(jobIndex, rankIndex).level}){MAINCOLOUR}`);
messagePlayerAlert(client, `{ALTCOLOUR}${getCharacterFullName(client)}{MAINCOLOUR} set your job rank to {ALTCOLOUR}${getJobRankData(jobIndex, rankIndex).name} (level ${getJobRankData(jobIndex, rankIndex).level}){MAINCOLOUR}`);
}
// ===========================================================================
function toggleJobRouteEnabledCommand(command, params, client) {
let jobId = getPlayerJob(client);
let jobRoute = getPlayerJobRoute(client);
@@ -2187,7 +2239,7 @@ function setJobRoutePayCommand(command, params, client) {
let amount = getParam(params, " ", 1);
if (isNaN(amount)) {
getLocaleString(client, "MustBeNumber", "amount");
getLocaleString(client, "MustBeNumber");
return false;
}
@@ -2480,8 +2532,10 @@ function startJobRoute(client, forceRoute = -1) {
getPlayerData(client).jobRouteLocation = 0;
getPlayerData(client).jobRouteVehicle = getPlayerVehicle(client);
getPlayerVehicle(client).colour1 = getJobRouteData(jobId, jobRoute).vehicleColour1;
getPlayerVehicle(client).colour2 = getJobRouteData(jobId, jobRoute).vehicleColour2;
if (isGameFeatureSupported("vehicleColour")) {
getPlayerVehicle(client).colour1 = getJobRouteData(jobId, jobRoute).vehicleColour1;
getPlayerVehicle(client).colour2 = getJobRouteData(jobId, jobRoute).vehicleColour2;
}
messagePlayerNormal(client, replaceJobRouteStringsInMessage(getJobRouteData(jobId, jobRoute).startMessage, jobId, jobRoute));
@@ -2528,7 +2582,7 @@ function stopJobRoute(client, successful = false, alertPlayer = true) {
stopReturnToJobVehicleCountdown(client);
sendPlayerStopJobRoute(client);
respawnVehicle(getPlayerData(client).jobRouteVehicle);
//respawnVehicle(getPlayerData(client).jobRouteVehicle);
getPlayerData(client).jobRouteVehicle = false;
getPlayerData(client).jobRoute = -1;
@@ -2558,6 +2612,7 @@ function getPlayerJobRouteVehicle(client) {
// ===========================================================================
function startReturnToJobVehicleCountdown(client) {
/*
getPlayerData(client).returnToJobVehicleTick = getGlobalConfig().returnToJobVehicleTime;
getPlayerData(client).returnToJobVehicleTimer = setInterval(function () {
//logToConsole(LOG_DEBUG, getPlayerData(client).returnToJobVehicleTick);
@@ -2572,6 +2627,7 @@ function startReturnToJobVehicleCountdown(client) {
stopJobRoute(client, false, true);
}
}, 1000);
*/
}
// ===========================================================================
@@ -2608,14 +2664,20 @@ function canPlayerUseJob(client, jobId) {
}
}
// Check if lowest rank is public rank
let lowestRank = getLowestJobRank(jobId);
if (getJobRankData(jobId, lowestRank).public == false) {
return false;
}
return true;
}
// ===========================================================================
function deleteJobLocation(jobIndex, jobLocationIndex) {
function deleteJobLocation(jobIndex, jobLocationIndex, whoDeleted = defaultNoAccountId) {
if (jobLocationData.databaseId > 0) {
quickDatabaseQuery(`DELETE FROM job_loc WHERE job_loc_id = ${getJobLocationData(jobIndex, jobLocationIndex).databaseId}`);
quickDatabaseQuery(`UPDATE job_loc SET job_loc_deleted = 1, job_loc_who_deleted = ${whoDeleted}, job_loc_when_deleted = UNIX_TIMESTAMP() WHERE job_loc_id = ${getJobLocationData(jobIndex, jobLocationIndex).databaseId}`);
}
deleteJobLocationBlip(jobIndex, jobLocationIndex);
@@ -2688,8 +2750,8 @@ function setAllJobDataIndexes() {
}
for (let v in getServerData().jobs[i].whiteList) {
getServerData().jobs[i].blackList[v].index = v;
getServerData().jobs[i].blackList[v].jobIndex = i;
getServerData().jobs[i].whiteList[v].index = v;
getServerData().jobs[i].whiteList[v].jobIndex = i;
}
for (let t in getServerData().jobs[i].routes) {
@@ -2803,6 +2865,7 @@ function saveJobRankToDatabase(jobRankData) {
["job_rank_level", jobRankData.level],
["job_rank_who_added", jobRankData.whoCreated],
["job_rank_when_added", jobRankData.whenCreated],
["job_rank_public", boolToInt(jobRankData.public)],
];
let dbQuery = null;
@@ -2827,6 +2890,13 @@ function saveJobRankToDatabase(jobRankData) {
// ===========================================================================
/**
* Saves a job route to database
*
* @param {JobRouteData} jobRouteData - The data of the job route
* @return {boolean} Whether the data saved (true) or not (false)
*
*/
function saveJobRouteToDatabase(jobRouteData) {
if (!jobRouteData) {
// Invalid job route data
@@ -2886,6 +2956,13 @@ function saveJobRouteToDatabase(jobRouteData) {
// ===========================================================================
/**
* Saves a job route location to database
*
* @param {JobRouteLocationData} jobRouteLocationData - The data of the job route location
* @return {boolean} Whether the data saved (true) or not (false)
*
*/
function saveJobRouteLocationToDatabase(jobRouteLocationData) {
if (!jobRouteLocationData) {
// Invalid job route position data
@@ -2893,7 +2970,7 @@ function saveJobRouteLocationToDatabase(jobRouteLocationData) {
}
if (jobRouteLocationData.needsSaved == false) {
logToConsole(LOG_DEBUG, `[V.RP.Job]: Job route location ${jobRouteLocationData.name} (DB ID ${jobRouteLocationData.databaseId}) doesn't need saved. Skipping ...`);
logToConsole(LOG_DEBUG, `[V.RP.Job]: Job route location ${jobRouteLocationData.name} (DB ID ${jobRouteLocationData.index}) doesn't need saved. Skipping ...`);
return false;
}
@@ -2929,13 +3006,20 @@ function saveJobRouteLocationToDatabase(jobRouteLocationData) {
disconnectFromDatabase(dbConnection);
return true;
}
logToConsole(LOG_DEBUG, `[V.RP.Job]: Saved job route location ${jobRoutePositionData.name} (${jobRouteLocationData.databaseId}) to database!`);
logToConsole(LOG_DEBUG, `[V.RP.Job]: Saved job route location ${jobRouteLocationData.name} (${jobRouteLocationData.index}) to database!`);
return false;
}
// ===========================================================================
/**
* Saves a job location to database
*
* @param {JobLocationData} jobLocationData - The data of the job location
* @return {boolean} Whether the data saved (true) or not (false)
*
*/
function saveJobLocationToDatabase(jobLocationData) {
if (jobLocationData == null) {
// Invalid job location data
@@ -2985,18 +3069,26 @@ function saveJobLocationToDatabase(jobLocationData) {
// ===========================================================================
/**
* Saves a job equipment to database
*
* @param {JobEquipmentData} jobEquipmentData - The data of the job equipment
* @return {boolean} Whether the data saved (true) or not (false)
*
*/
function saveJobEquipmentToDatabase(jobEquipmentData) {
if (jobEquipmentData == null) {
// Invalid job equipment data
logToConsole(LOG_DEBUG, `[V.RP.Job]: Job equipment ${jobEquipmentData.index} is invalid. Skipping ...`);
return false;
}
if (!jobEquipmentData.needsSaved) {
logToConsole(LOG_DEBUG, `[V.RP.Job]: Job equipment ${jobEquipmentData.name} (${jobEquipmentData.databaseId}) doesn't need saved. Skipping ...`);
logToConsole(LOG_DEBUG, `[V.RP.Job]: Job equipment ${jobEquipmentData.name} (${jobEquipmentData.index}) doesn't need saved. Skipping ...`);
return false;
}
logToConsole(LOG_DEBUG, `[V.RP.Job]: Saving job equipment ${jobEquipmentData.databaseId} to database ...`);
logToConsole(LOG_DEBUG, `[V.RP.Job]: Saving job equipment ${jobEquipmentData.index} to database ...`);
let dbConnection = connectToDatabase();
if (dbConnection) {
let safeName = escapeDatabaseString(dbConnection, jobEquipmentData.name);
@@ -3024,25 +3116,33 @@ function saveJobEquipmentToDatabase(jobEquipmentData) {
disconnectFromDatabase(dbConnection);
return true;
}
logToConsole(LOG_DEBUG, `[V.RP.Job]: Saved job equipment ${jobEquipmentData.databaseId} to database`);
logToConsole(LOG_DEBUG, `[V.RP.Job]: Saved job equipment ${jobEquipmentData.index} to database`);
return false;
}
// ===========================================================================
/**
* Saves a job equipment item to database
*
* @param {JobEquipmentItemData} jobEquipmentItemData - The data of the job equipment item
* @return {boolean} Whether the data saved (true) or not (false)
*
*/
function saveJobEquipmentItemToDatabase(jobEquipmentItemData) {
if (jobEquipmentItemData == null) {
logToConsole(LOG_DEBUG, `[V.RP.Job]: Job equipment item ${jobEquipmentItemData.index} is invalid. Skipping ...`);
// Invalid job equipment weapon data
return false;
}
if (!jobEquipmentItemData.needsSaved) {
logToConsole(LOG_DEBUG, `[V.RP.Job]: Job equipment item ${jobEquipmentItemData.databaseId} doesn't need saved. Skipping ...`);
logToConsole(LOG_DEBUG, `[V.RP.Job]: Job equipment item ${jobEquipmentItemData.index} doesn't need saved. Skipping ...`);
return false;
}
logToConsole(LOG_DEBUG, `[V.RP.Job]: Saving job equipment weapon ${jobEquipmentItemData.databaseId} to database ...`);
logToConsole(LOG_DEBUG, `[V.RP.Job]: Saving job equipment weapon ${jobEquipmentItemData.index} to database ...`);
let dbConnection = connectToDatabase();
if (dbConnection) {
let data = [
@@ -3069,25 +3169,32 @@ function saveJobEquipmentItemToDatabase(jobEquipmentItemData) {
disconnectFromDatabase(dbConnection);
return true;
}
logToConsole(LOG_DEBUG, `[V.RP.Job]: Saved job equipment weapon ${jobEquipmentItemData.databaseId} to database`);
logToConsole(LOG_DEBUG, `[V.RP.Job]: Saved job equipment weapon ${jobEquipmentItemData.index} to database`);
return false;
}
// ===========================================================================
/**
* Saves a job uniform to database
*
* @param {JobUniformData} jobUniformData - The data of the job uniform
* @return {boolean} Whether the data saved (true) or not (false)
*
*/
function saveJobUniformToDatabase(jobUniformData) {
if (jobUniformData == null) {
// Invalid job uniform data
logToConsole(LOG_DEBUG, `[V.RP.Job]: Job uniform ${jobUniformData.index} is invalid. Skipping ...`);
return false;
}
if (!jobUniformData.needSaved) {
logToConsole(LOG_DEBUG, `[V.RP.Job]: Job uniform ${jobUniformData.databaseId} doesn't need saved. Skipping ...`);
if (jobUniformData.needSaved == false) {
logToConsole(LOG_DEBUG, `[V.RP.Job]: Job uniform ${jobUniformData.index} doesn't need saved. Skipping ...`);
return false;
}
logToConsole(LOG_DEBUG, `[V.RP.Job]: Saving job uniform ${jobUniformData.databaseId} to database ...`);
logToConsole(LOG_DEBUG, `[V.RP.Job]: Saving job uniform ${jobUniformData.index} to database ...`);
let dbConnection = connectToDatabase();
if (dbConnection) {
let safeName = escapeDatabaseString(dbConnection, jobUniformData.name);
@@ -3116,7 +3223,7 @@ function saveJobUniformToDatabase(jobUniformData) {
disconnectFromDatabase(dbConnection);
return true;
}
logToConsole(LOG_DEBUG, `[V.RP.Job]: Saved job uniform ${jobUniformData.databaseId} to database`);
logToConsole(LOG_DEBUG, `[V.RP.Job]: Saved job uniform ${jobUniformData.index} to database`);
return false;
}
@@ -3580,7 +3687,7 @@ function createJobUniformCommand(command, params, client) {
}
createJobUniform(jobId, skinIndex);
messageAdmins(`{adminOrange}${getPlayerName(client)}{MAINCOLOUR} created uniform with skin {ALTCOLOUR}${getSkinNameFromIndex(skinIndex)} (${getGameConfig().skins[skinIndex][0]}){MAINCOLOUR} for job {jobYellow}${getJobData(jobId).name}`);
messageAdmins(`{adminOrange}${getPlayerName(client)}{MAINCOLOUR} created uniform with skin {ALTCOLOUR}${getSkinNameFromIndex(skinIndex)} (${getGameConfig().skins[getGame()][skinIndex][0]}){MAINCOLOUR} for job {jobYellow}${getJobData(jobId).name}`);
return true;
}
@@ -3638,10 +3745,12 @@ function createJobUniform(jobId, skinIndex) {
let tempJobUniformData = new JobUniformData(false);
tempJobUniformData.skin = skinIndex;
tempJobUniformData.jobIndex = jobId;
tempJobUniformData.job = getJobData(jobId);
tempJobUniformData.job = getJobData(jobId).databaseId;
tempJobUniformData.name = getGameConfig().skins[getGame()][skinIndex][1];
tempJobUniformData.needsSaved = true;
getJobData(jobId).uniforms.push(tempJobUniformData);
setAllJobDataIndexes();
}
@@ -3653,7 +3762,7 @@ function deleteJobRouteLocationCommand(command, params, client) {
messageAdmins(`{adminOrange}${getPlayerName(client)}{MAINCOLOUR} deleted route location {ALTCOLOUR}${closestJobRouteLocation.index} (DB ID ${closestJobRouteLocation.databaseId}){MAINCOLOUR} for the {ALTCOLOUR}${closestJobRouteLocation.name}{jobYellow} route of the {jobYellow}${getJobData(closestJobLocation.jobIndex).name}{MAINCOLOUR} job`);
if (closestJobRouteLocation.databaseId > 0) {
quickDatabaseQuery(`DELETE FROM job_route_loc WHERE job_route_loc_id = ${closestJobRouteLocation.databaseId}`);
quickDatabaseQuery(`UPDATE job_route_loc SET job_route_loc_deleted = 1, job_route_loc_who_deleted = ${getPlayerData(client).accountData.databaseId}, job_route_loc_when_deleted = UNIX_TIMESTAMP() WHERE job_route_loc_id = ${closestJobRouteLocation.databaseId}`);
}
let tempIndex = closestJobRouteLocation.index;
@@ -3691,8 +3800,8 @@ function deleteJobRouteCommand(command, params, client) {
messageAdmins(`{adminOrange}${getPlayerName(client)}{MAINCOLOUR} deleted route {ALTCOLOUR}${jobRouteData.name} (DB ID ${jobRouteData.databaseId}){MAINCOLOUR} for the {jobYellow}${getJobData(jobId).name}{MAINCOLOUR} job`);
if (jobRouteData.databaseId > 0) {
quickDatabaseQuery(`DELETE FROM job_route WHERE job_route_id = ${jobRouteData.databaseId}`);
quickDatabaseQuery(`DELETE FROM job_route_loc WHERE job_route_loc_route = ${jobRouteData.databaseId}`);
quickDatabaseQuery(`UPDATE job_route SET job_route_deleted = 1, job_route_who_deleted = ${getPlayerData(client).accountData.databaseId}, job_route_when_deleted = UNIX_TIMESTAMP() WHERE job_route_id = ${jobRouteData.databaseId}`);
quickDatabaseQuery(`UPDATE job_route_loc SET job_route_loc_deleted = 1, job_route_loc_who_deleted = ${getPlayerData(client).accountData.databaseId}, job_route_loc_when_deleted = UNIX_TIMESTAMP() WHERE job_route_loc_route = ${jobRouteData.databaseId}`);
}
clearArray(getServerData().jobs[jobId].routes[jobRoute].locations);
@@ -3714,7 +3823,7 @@ function deleteJobUniformCommand(command, params, client) {
}
if (isNaN(uniformIndex)) {
messagePlayerError(client, getLocaleString(client, "MustBeNumber", "uniform ID"));
messagePlayerError(client, getLocaleString(client, "MustBeNumber"));
return false;
}
@@ -3723,7 +3832,7 @@ function deleteJobUniformCommand(command, params, client) {
return false;
}
quickDatabaseQuery(`DELETE FROM job_uniform WHERE job_uniform_id = ${getJobData(jobId).uniforms[uniformIndex].databaseId}`);
quickDatabaseQuery(`UPDATE job_uniform SET job_uniform_deleted = 1, job_uniform_who_deleted = ${getPlayerData(client).accountData.databaseId}, job_uniform_when_deleted = UNIX_TIMESTAMP() WHERE job_uniform_id = ${getJobData(jobId).uniforms[uniformIndex].databaseId}`);
getJobData(jobId).uniforms.splice(uniformIndex, 1);
setAllJobDataIndexes();
@@ -3893,7 +4002,7 @@ function getJobEquipmentItemData(jobIndex, equipmentIndex, equipmentItemIndex) {
/**
* @param {number} jobIndex - The data index of the job
* @param {number} rankIndex - The data index of the job rank
* @return {JobRouteData} The job rank's data (class instance)
* @return {JobRankData} The job rank's data (class instance)
*/
function getJobRankData(jobIndex, rankIndex) {
if (typeof getServerData().jobs[jobIndex] == "undefined") {
@@ -4010,7 +4119,7 @@ function finishSuccessfulJobRoute(client) {
stopReturnToJobVehicleCountdown(client);
sendPlayerStopJobRoute(client);
respawnVehicle(getPlayerData(client).jobRouteVehicle);
//respawnVehicle(getPlayerData(client).jobRouteVehicle);
getPlayerData(client).jobRouteVehicle = false;
getPlayerData(client).jobRoute = -1;
@@ -4179,4 +4288,178 @@ function doesJobLocationHaveAnyRoutes(jobLocationData) {
return (getRandomJobRouteForLocation(jobLocationData) != -1);
}
// ===========================================================================
/**
* @param {Number} jobIndex - The job index to search ranks for
* @param {String} params - The params to search for
* @return {Number} The data index of a matching job
*/
function getJobRankFromParams(jobIndex, params) {
if (isNaN(params)) {
for (let i in getJobData(jobIndex).ranks) {
if ((toLowerCase(getJobData(jobIndex).ranks[i].name).indexOf(toLowerCase(params)) != -1)) {
return i;
}
}
} else {
for (let i in getJobData(jobIndex).ranks) {
if (getJobData(jobIndex).ranks[i].level == toInteger(params)) {
return i;
}
}
}
return false;
}
// ===========================================================================
function getJobRoutesCommand(command, params, client) {
let closestJobLocation = getClosestJobLocation(getPlayerPosition(client));
if (!closestJobLocation) {
messagePlayerAlert(client, getLocaleString(client, "InvalidJob"));
return false;
}
let jobData = getJobData(closestJobLocation.jobIndex);
let jobRoutesList = jobData.routes.map(function (r) {
return `{chatBoxListIndex}${r.index}: ${(r.enabled) ? "{softGreen}" : "{softRed}"}${r.name} {ALTCOLOUR}(${r.locations.length} stops, added ${getTimeDifferenceDisplay(getCurrentUnixTimestamp(), r.whenCreated)} ago)`;
});
let chunkedList = splitArrayIntoChunks(jobRoutesList, 2);
messagePlayerNormal(client, makeChatBoxSectionHeader(getLocaleString(client, "HeaderJobRoutesList", `${jobData.name}, Location ${closestJobLocation.index}`)));
for (let i in chunkedList) {
messagePlayerInfo(client, chunkedList[i].join(", "));
}
}
// ===========================================================================
function getJobRouteInfoCommand(command, params, client) {
if (areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
if (!areThereEnoughParams(params, 2, " ")) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
let jobIndex = getJobFromParams(getParam(params, " ", 1));
if (jobIndex == -1) {
messagePlayerSyntax(client, getLocaleString(client, "InvalidJob"));
return false;
}
let routeIndex = getJobRouteFromParams(getParam(params, " ", 2), jobIndex);
if (routeIndex == -1) {
messagePlayerSyntax(client, getLocaleString(client, "InvalidJobRoute"));
return false;
}
let jobRouteData = getJobRouteData(jobIndex, routeIndex);
let jobData = getJobData(jobRouteData.jobIndex);
let tempStats = [
[`ID`, `${jobRouteData.index}/${jobRouteData.databaseId}`],
[`Job`, `${jobData.name}`],
[`Name`, `${jobRouteData.name}`],
[`Added By`, `${loadAccountFromId(jobRouteData.whoCreated).name}`],
[`Added On`, `${new Date(jobRouteData.whenCreated * 1000).toLocaleDateString("en-GB")}`],
[`Enabled`, `${getYesNoFromBool(jobRouteData.enabled)}`],
[`Stops`, `${jobRouteData.locations.length}`],
[`Pay`, `${getCurrencyString(jobRouteData.pay)}`],
//[`Start Message`, `${jobRouteData.startMessage}`],
//[`Finish Message`, `${jobRouteData.finishMessage}`],
//[`Location Goto Message`, `${jobRouteData.locationGotoMessage}`],
//[`Location Arrive Message`, `${jobRouteData.locationArriveMessage}`],
//[`Location Arrive Message`, `${jobRouteData.locationArriveMessage}`],
[`Vehicle Colour`, `${getVehicleColourInfoString(jobRouteData.vehicleColour1, false)}, ${getVehicleColourInfoString(jobRouteData.vehicleColour2, false)}`],
];
let stats = tempStats.map(stat => `{chatBoxListIndex}${stat[0]}: {ALTCOLOUR}${stat[1]}{MAINCOLOUR}`);
messagePlayerNormal(client, makeChatBoxSectionHeader(getLocaleString(client, "HeaderJobRouteInfo", `${jobData.name}, Location ${jobRouteData.index}`)));
let chunkedList = splitArrayIntoChunks(stats, 4);
for (let i in chunkedList) {
messagePlayerInfo(client, chunkedList[i].join(", "));
}
}
// ===========================================================================
function jobInviteCommand(command, params, client) {
if (areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
if (getPlayerJob(client) == -1) {
messagePlayerError(client, getLocaleString(client, "InvalidJob"));
return false;
}
if (!doesPlayerHaveJobPermission(client, getJobFlagValue("AddMember"))) {
messagePlayerError(client, getLocaleString(client, "CantAddJobMembers"));
return false;
}
let targetClient = getPlayerFromParams(params);
if (getPlayerJob(targetClient) != -1) {
messagePlayerError(client, getLocaleString(client, "JobInviteAlreadyHasJob"));
return false;
}
messagePlayerSuccess(client, getLocaleString(client, "JobInviteSent", `{ALTCOLOUR}${getCharacterFullName(targetClient)}{MAINCOLOUR}`));
showPlayerPrompt(targetClient, getLocaleString(targetClient, "JobInviteRequest", `{ALTCOLOUR}${getCharacterFullName(client)}{MAINCOLOUR}`, `{jobYellow}${getJobData(getPlayerJob(client)).name}{MAINCOLOUR}`, getLocaleString(targetClient, "GUIAlertTitle"), getLocaleString(targetClient, "Yes"), getLocaleString(targetClient, "No")));
getPlayerData(targetClient).promptType = V_PROMPT_JOBINVITE;
getPlayerData(targetClient).promptValue = getPlayerJob(client);
}
// ===========================================================================
function jobUninviteCommand(command, params, client) {
if (areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
if (getPlayerJob(client) == -1) {
messagePlayerError(client, getLocaleString(client, "InvalidJob"));
return false;
}
if (!doesPlayerHaveJobPermission(client, getJobFlagValue("RemoveMember"))) {
messagePlayerError(client, getLocaleString(client, "CantRemoveJobMembers"));
return false;
}
let targetClient = getPlayerFromParams(params);
if (getPlayerJob(targetClient) != getPlayerJob(client)) {
messagePlayerError(client, getLocaleString(client, "JobUnInviteNotInJob"));
return false;
}
if (getJobRankData(getPlayerJob(client), getPlayerJobRank(client)).level <= getJobRankData(getPlayerJob(targetClient), getPlayerJobRank(targetClient)).level) {
messagePlayerError(client, getLocaleString(client, "JobUnInviteTooLow"));
return false;
}
messagePlayerSuccess(client, getLocaleString(client, "PlayerRemovedFromJob", `{ALTCOLOUR}${getCharacterFullName(targetClient)}{MAINCOLOUR}`));
messagePlayerAlert(targetClient, getLocaleString(client, "RemovedFromJob", `{ALTCOLOUR}${getCharacterFullName(client)}{MAINCOLOUR}`));
stopWorking(targetClient);
getPlayerCurrentSubAccount(targetClient).job = 0;
getPlayerCurrentSubAccount(targetClient).jobIndex = -1;
getPlayerCurrentSubAccount(targetClient).jobRank = 0;
getPlayerCurrentSubAccount(targetClient).jobRankIndex = -1;
}
// ===========================================================================

View File

@@ -58,7 +58,7 @@ function addKeyBindCommand(command, params, client) {
if (!keyId) {
messagePlayerError(client, getLocaleString(client, "InvalidKeyBindName"));
messagePlayerTip(client, getLocaleString(client, "KeyBindNameTip"));
messagePlayerInfo(client, getLocaleString(client, "UniversalInlineExampleList", `{ALTCOLOUR}1, 2, a, b, numplus, num1, f1, f2, pageup, delete, insert, rightshift, leftctrl{MAINCOLOR}`));
messagePlayerInfo(client, getLocaleString(client, "UniversalInlineExamplesList", `{ALTCOLOUR}1, 2, a, b, numplus, num1, f1, f2, pageup, delete, insert, rightshift, leftctrl{MAINCOLOR}`));
return false;
}

View File

@@ -264,34 +264,34 @@ function reloadLocaleConfigurationCommand(command, params, client) {
// ===========================================================================
async function translateMessage(messageText, translateFrom = getGlobalConfig().locale.defaultLanguageId, translateTo = getGlobalConfig().locale.defaultLanguageId) {
return new Promise(resolve => {
if (translateFrom == translateTo) {
resolve(messageText);
}
function translateMessage(messageText, translateFrom = getGlobalConfig().locale.defaultLanguageId, translateTo = getGlobalConfig().locale.defaultLanguageId) {
//return new Promise(resolve => {
if (translateFrom == translateTo) {
resolve(messageText);
}
for (let i in cachedTranslations[translateFrom][translateTo]) {
if (cachedTranslations[translateFrom][translateTo][i][0] == messageText) {
logToConsole(LOG_DEBUG, `[Translate]: Using existing translation for ${getGlobalConfig().locale.locales[translateFrom].englishName} to ${getGlobalConfig().locale.locales[translateTo].englishName} - (${messageText}), (${cachedTranslations[translateFrom][translateTo][i][1]})`);
resolve(cachedTranslations[translateFrom][translateTo][i][1]);
return true;
}
for (let i in cachedTranslations[translateFrom][translateTo]) {
if (cachedTranslations[translateFrom][translateTo][i][0] == messageText) {
logToConsole(LOG_DEBUG, `[Translate]: Using existing translation for ${getGlobalConfig().locale.locales[translateFrom].englishName} to ${getGlobalConfig().locale.locales[translateTo].englishName} - (${messageText}), (${cachedTranslations[translateFrom][translateTo][i][1]})`);
resolve(cachedTranslations[translateFrom][translateTo][i][1]);
return true;
}
}
let thisTranslationURL = getGlobalConfig().locale.translateURL.format(encodeURIComponent(messageText), toUpperCase(getGlobalConfig().locale.locales[translateFrom].isoCode), toUpperCase(getGlobalConfig().locale.locales[translateTo].isoCode), getGlobalConfig().locale.apiEmail);
httpGet(
thisTranslationURL,
"",
function (data) {
data = ArrayBufferToString(data);
let translationData = JSON.parse(data);
cachedTranslations[translateFrom][translateTo].push([messageText, translationData.responseData.translatedText]);
resolve(translationData.responseData.translatedText);
},
function (data) {
}
);
});
let thisTranslationURL = getGlobalConfig().locale.translateURL.format(encodeURIComponent(messageText), toUpperCase(getGlobalConfig().locale.locales[translateFrom].isoCode), toUpperCase(getGlobalConfig().locale.locales[translateTo].isoCode), getGlobalConfig().locale.apiEmail);
httpGet(
thisTranslationURL,
"",
function (data) {
data = ArrayBufferToString(data);
let translationData = JSON.parse(data);
cachedTranslations[translateFrom][translateTo].push([messageText, translationData.responseData.translatedText]);
resolve(translationData.responseData.translatedText);
},
function (data) {
}
);
//});
}
// ===========================================================================

View File

@@ -136,6 +136,12 @@ function messagePlayerTalk(client, talkingClient, messageText) {
// ===========================================================================
function messagePlayerPhone(client, talkingClient, messageText) {
messagePlayerNormal(client, `🗣️ ${getPlayerAccentInlineOutput(talkingClient)}${getClientSubAccountName(talkingClient)} says (phone): ${messageText}`, getColourByType("talkMessage"));
}
// ===========================================================================
function messagePlayerWhisper(client, whisperingClient, messageText) {
messagePlayerNormal(client, `🤫 ${getPlayerAccentInlineOutput(whisperingClient)}${getClientSubAccountName(whisperingClient)} whispers: ${messageText}`, getColourByType("whisperMessage"));
}
@@ -244,22 +250,47 @@ function messagePlayerPrivateMessage(toClient, fromClient, messageText) {
// ===========================================================================
function showPlayerInfo(client, infoMessage, infoTitle = "Info") {
//if (doesPlayerUseGUI(client)) {
// showPlayerErrorGUI(client, errorMessage, errorTitle, getLocaleString(client, "GUIOkButton"));
//} else {
messagePlayerInfo(client, infoMessage);
//}
}
// ===========================================================================
function showPlayerError(client, errorMessage, errorTitle = "Error") {
if (doesPlayerUseGUI(client)) {
showPlayerErrorGUI(client, errorMessage, errorTitle);
} else {
messagePlayerError(client, errorMessage);
}
//if (doesPlayerUseGUI(client)) {
// showPlayerErrorGUI(client, errorMessage, errorTitle, getLocaleString(client, "GUIOkButton"));
//} else {
messagePlayerError(client, errorMessage);
//}
}
// ===========================================================================
function showPlayerAlert(client, alertMessage, alertTitle = "Alert") {
if (doesPlayerUseGUI(client)) {
showPlayerInfoGUI(client, alertMessage, alertTitle);
} else {
messagePlayerAlert(client, alertMessage);
//if (doesPlayerUseGUI(client)) {
// showPlayerInfoGUI(client, alertMessage, alertTitle);
//} else {
messagePlayerAlert(client, alertMessage);
//}
}
// ===========================================================================
function messagePlayerPhoneCall(talkingPlayer, receivingPlayer, messageText) {
let clients = getClients();
for (let i in clients) {
if (isPlayerSpawned(clients[i])) {
if (hasBitFlag(getPlayerData(clients[i]).accountData.flags.moderation, getModerationFlagValue("CanHearEverything")) || (getDistance(getPlayerPosition(talkingPlayer), getPlayerPosition(clients[i])) <= getGlobalConfig().talkDistance && getPlayerDimension(talkingPlayer) == getPlayerDimension(clients[i]))) {
messagePlayerPhone(clients[i], talkingPlayer, messageText);
}
}
}
messagePlayerNormal(receivingPlayer, `📞 {ALTCOLOUR}(On Phone): {MAINCOLOUR}${messageText}`);
}
// ===========================================================================

View File

@@ -364,19 +364,23 @@ function enterExitPropertyCommand(command, params, client) {
getPlayerData(client).enteringExitingProperty = [(isBusiness) ? V_PROPERTY_TYPE_BUSINESS : V_PROPERTY_TYPE_HOUSE, closestProperty.index];
meActionToNearbyPlayers(client, getLanguageLocaleString(englishId, "EntersProperty", typeString, nameString));
if (closestProperty.exitScene != "" && isGameFeatureSupported("interiorScene")) {
getPlayerCurrentSubAccount(client).spawnPosition = closestProperty.exitPosition;
if (isMainWorldScene(closestProperty.exitScene) || closestProperty.exitScene == "V.MAINWORLD") {
setPlayerScene(client, getGameConfig().mainWorldScene[getGame()]);
} else {
setPlayerScene(client, closestProperty.exitScene);
}
return false;
}
setPlayerDimension(client, 50000 + getPlayerId(client));
if (isFadeCameraSupported()) {
fadePlayerCamera(client, false, 1000);
fadePlayerCamera(client, false, 2000);
}
if (closestProperty.exitScene != "" && isGameFeatureSupported("interiorScene")) {
setTimeout(function () {
getPlayerCurrentSubAccount(client).spawnPosition = closestProperty.exitPosition;
if (isMainWorldScene(closestProperty.exitScene)) {
setPlayerScene(client, getGameConfig().mainWorldScene[getGame()]);
} else {
setPlayerScene(client, closestProperty.exitScene);
}
}, 2000);
return false;
}
setTimeout(function () {
@@ -397,21 +401,22 @@ function enterExitPropertyCommand(command, params, client) {
meActionToNearbyPlayers(client, getLanguageLocaleString(englishId, "ExitsProperty", typeString, nameString));
if (closestProperty.entranceScene != "" && isGameFeatureSupported("interiorScene")) {
getPlayerCurrentSubAccount(client).spawnPosition = closestProperty.entrancePosition;
if (isMainWorldScene(closestProperty.entranceScene) || closestProperty.entranceScene == "V.MAINWORLD") {
destroyGameElement(client.player);
setPlayerScene(client, getGameConfig().mainWorldScene[getGame()]);
} else {
destroyGameElement(client.player);
setPlayerScene(client, closestProperty.entranceScene);
}
return false;
if (isFadeCameraSupported()) {
fadePlayerCamera(client, false, 2000);
}
if (isFadeCameraSupported()) {
fadePlayerCamera(client, false, 1000);
if (closestProperty.entranceScene != "" && isGameFeatureSupported("interiorScene")) {
setTimeout(function () {
getPlayerCurrentSubAccount(client).spawnPosition = closestProperty.entrancePosition;
if (isMainWorldScene(closestProperty.entranceScene)) {
destroyGameElement(client.player);
setPlayerScene(client, getGameConfig().mainWorldScene[getGame()]);
} else {
destroyGameElement(client.player);
setPlayerScene(client, closestProperty.entranceScene);
}
}, 2000);
return false;
}
setTimeout(function () {
@@ -468,7 +473,7 @@ function getPlayerInfoCommand(command, params, client) {
["Account", `${getPlayerData(targetClient).accountData.name}{mediumGrey}[${getPlayerData(targetClient).accountData.databaseId}]{ALTCOLOUR}`],
["Character", `${getCharacterFullName(targetClient)}{mediumGrey}[${getPlayerCurrentSubAccount(targetClient).databaseId}]{ALTCOLOUR}`],
["Connected", `${getTimeDifferenceDisplay(getCurrentUnixTimestamp(), getPlayerData(targetClient).connectTime)} ago`],
["Registered", `${registerDate.toLocaleDateString()}`],
["Registered", `${registerDate.toLocaleDateString("en-GB")}`],
["Game Version", `${targetClient.gameVersion}`],
["Script Version", `${scriptVersion}`],
["Client Version", `${getPlayerData(targetClient).clientVersion}`],
@@ -476,7 +481,7 @@ function getPlayerInfoCommand(command, params, client) {
["Skin", `${skinName}{mediumGrey}[Model: ${skinModel}/Index: ${skinIndex}]{ALTCOLOUR}`],
["Clan", `${clan}`],
["Job", `${job}`],
["Current Date", `${currentDate.toLocaleDateString()}`],
["Current Date", `${currentDate.toLocaleDateString("en-GB")}`],
];
let stats = tempStats.map(stat => `{MAINCOLOUR}${stat[0]}: {ALTCOLOUR}${stat[1]} {MAINCOLOUR}`);
@@ -521,12 +526,12 @@ function checkPlayerSpawning() {
// ===========================================================================
function showPlayerPrompt(client, promptMessage, promptTitle, yesButtonText, noButtonText) {
if (doesPlayerUseGUI(client)) {
showPlayerPromptGUI(client, promptMessage, promptTitle, yesButtonText, noButtonText);
} else {
messagePlayerNormal(client, `🛎️ ${promptMessage} `);
messagePlayerInfo(client, getLocaleString(client, "PromptResponseTip", `{ALTCOLOUR}/yes{MAINCOLOUR}`, `{ALTCOLOUR}/no{MAINCOLOUR}`));
}
//if (doesPlayerUseGUI(client)) {
// showPlayerPromptGUI(client, promptMessage, promptTitle, yesButtonText, noButtonText);
//} else {
messagePlayerNormal(client, `🛎️ ${promptMessage} `);
messagePlayerInfo(client, getLocaleString(client, "PromptResponseTip", `{ALTCOLOUR}/yes{MAINCOLOUR}`, `{ALTCOLOUR}/no{MAINCOLOUR}`));
//}
}
// ===========================================================================
@@ -1012,4 +1017,39 @@ function getPlayerInPropertyData(client) {
getPlayerData(client).inProperty = null;
}
// ===========================================================================
function scoreBoardCommand(command, params, client) {
// Handled client side
return false;
}
// ===========================================================================
function locatePlayerCommand(client) {
if (isPlayerSpawned(client)) {
messagePlayerError(client, getLocaleString(client, "MustBeSpawned"));
return false;
}
if (areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
let targetClient = getPlayerFromParams(client);
if (!targetClient) {
messagePlayerError(client, getLocaleString(client, "InvalidPlayer"));
return false;
}
if (isPlayerSpawned(targetClient)) {
messagePlayerError(client, getLocaleString(client, "InvalidPlayer"));
return false;
}
messagePlayerInfo(client, getLocaleString(client, "PlayerLocateDistanceAndDirection", `{ALTCOLOUR}${getCharacterFullName(targetClient)}{MAINCOLOUR}`, `{ALTCOLOUR}${getDistance(getPlayerPosition(client), getPlayerPosition(targetClient))}{MAINCOLOUR}`, `{ALTCOLOUR}${getLocaleString(client, getCardinalDirectionName(getCardinalDirection(getPlayerPosition(client), getPlayerPosition(targetClient))))}`))
}
// ===========================================================================

View File

@@ -499,7 +499,7 @@ function getPlayerName(client) {
// ===========================================================================
function getServerName() {
return "Asshat Gaming RP";
return "Connected Roleplay";
}
// ===========================================================================
@@ -619,9 +619,9 @@ function setVehicleEngine(vehicle, engine) {
// ===========================================================================
function setVehicleLocked(vehicle, locked) {
vehicle.locked = locked;
setEntityData(vehicle, "v.rp.locked", locked, true);
sendNetworkEventToPlayer("v.rp.veh.locked", null, vehicle.id, locked);
vehicle.locked = locked;
}
// ===========================================================================
@@ -815,29 +815,18 @@ function getVehicleName(vehicle) {
// ===========================================================================
function getElementModel(element) {
if (typeof element.modelIndex != "undefined") {
return element.modelIndex;
}
if (typeof element.model != "undefined") {
return element.model;
}
return element.modelIndex;
}
// ===========================================================================
function givePlayerWeaponAmmo(client, ammo) {
givePlayerWeapon(client, getPlayerWeapon(client), getPlayerWeaponAmmo(client) + ammo);
}
// ===========================================================================
function getPlayerWeapon(client) {
if (areServerElementsSupported(client)) {
return getPlayerPed(client).weapon;
} else {
return getPlayerData(client).syncWeapon;
}
return getPlayerPed(client).weapon;
}
// ===========================================================================
@@ -889,10 +878,10 @@ function disconnectFromDatabase(dbConnection, force = false) {
function queryDatabase(dbConnection, queryString, useThread = false) {
logToConsole(LOG_DEBUG, `[V.RP.Database] Query string: ${queryString}`);
if (useThread == true) {
Promise.resolve().then(() => {
let queryResult = dbConnection.query(queryString);
return queryResult;
});
//Promise.resolve().then(() => {
let queryResult = dbConnection.query(queryString);
return queryResult;
//});
} else {
return dbConnection.query(queryString);
}
@@ -1021,72 +1010,6 @@ function executeDatabaseQueryCommand(command, params, client) {
// ===========================================================================
function setConstantsAsGlobalVariablesInDatabase() {
let dbConnection = connectToDatabase();
let entries = Object.entries(global);
for (let i in entries) {
logToConsole(LOG_DEBUG, `[V.RP.Database] Checking entry ${i} (${entries[i]})`);
if (toString(i).slice(0, 3).indexOf("V_") != -1) {
logToConsole(LOG_DEBUG, `[V.RP.Database] Adding ${i} (${entries[i]}) to database global variables`);
}
}
}
// ===========================================================================
function createDatabaseInsertQuery(tableName, data) {
let fields = [];
let values = [];
for (let i in data) {
if (data[i][1] != "undefined" && data[i][1] != NaN && data[i][0] != 'NaN') {
if (data[i][1] != "undefined" && data[i][1] != NaN && data[i][1] != 'NaN') {
fields.push(data[i][0]);
if (typeof data[i][1] == "string") {
if (data[i][1] == "{UNIXTIMESTAMP}") {
values.push("UNIX_TIMESTAMP()");
} else {
values.push(`'${data[i][1]}'`);
}
} else {
values.push(data[i][1]);
}
}
}
}
let queryString = `INSERT INTO ${tableName} (${fields.join(", ")}) VALUES (${values.join(", ")})`;
return queryString;
}
// ===========================================================================
function createDatabaseUpdateQuery(tableName, data, whereClause) {
let values = [];
for (let i in data) {
if (data[i][0] != "undefined" && data[i][0] != NaN && data[i][0] != 'NaN') {
if (data[i][1] != "undefined" && data[i][1] != NaN && data[i][1] != 'NaN') {
if (typeof data[i][1] == "string") {
if (data[i][1] == "{UNIXTIMESTAMP}") {
values.push(`${data[i][0]}=UNIX_TIMESTAMP()`);
} else {
values.push(`${data[i][0]}='${data[i][1]}'`);
}
} else {
values.push(`${data[i][0]}=${data[i][1]}`);
}
}
}
}
let queryString = `UPDATE ${tableName} SET ${values.join(", ")} WHERE ${whereClause}`;
return queryString;
}
// ===========================================================================
function sendNetworkEventToPlayer(eventName, client, ...args) {
let argsArray = [eventName, client];
argsArray = argsArray.concat(args);
@@ -1391,38 +1314,6 @@ function setVehicleTrunkState(vehicle, trunkState) {
// ===========================================================================
/*
function addAllEventHandlers() {
bindServerEventHandler("onResourceStart", onResourceStart)
bindServerEventHandler("onResourceStop", onResourceStart)
addServerEventHandler("onServerStop", onResourceStart);
addServerEventHandler("onResourceStart", onResourceStart);
addServerEventHandler("onResourceStop", onResourceStop);
addServerEventHandler("onServerStop", onResourceStop);
addServerEventHandler("onProcess", onProcess);
addServerEventHandler("onEntityProcess", onEntityProcess);
addServerEventHandler("onPlayerConnect", onInitialConnectionToServer);
addServerEventHandler("onPlayerJoin", onPlayerJoin);
addServerEventHandler("onPlayerJoined", onPlayerJoined);
addServerEventHandler("onPlayerChat", onPlayerChat);
addServerEventHandler("onPlayerQuit", onPlayerQuit);
addServerEventHandler("onElementStreamIn", onElementStreamIn);
addServerEventHandler("onElementStreamOut", onElementStreamOut);
addServerEventHandler("onPedSpawn", onPedSpawn);
addServerEventHandler("onPedEnterVehicle", onPedEnteringVehicle);
addServerEventHandler("onPedExitVehicle", onPedExitingVehicle);
addServerEventHandler("onPedEnteringVehicle", onPedEnteringVehicle);
addServerEventHandler("onPedExitingVehicle", onPedExitingVehicle);
}
*/
// ===========================================================================
function addServerCommandHandler(command, handlerFunction) {
addCommandHandler(command, handlerFunction);
}
@@ -1533,7 +1424,7 @@ function setServerName(name) {
// ===========================================================================
function setServerPassword(password) {
server.setPassword(password);
//server.setPassword(password);
}
// ===========================================================================
@@ -1548,4 +1439,51 @@ function setServerRule(ruleName, ruleValue) {
server.setRule(ruleName, ruleValue);
}
// ===========================================================================
function addAllEventHandlers() {
addEventHandler("onResourceStart", onResourceStart);
addEventHandler("onResourceStop", onResourceStop);
addEventHandler("onProcess", onProcess);
addEventHandler("onPlayerConnect", onPlayerConnect);
addEventHandler("onPlayerJoin", onPlayerJoin);
addEventHandler("onPlayerJoined", onPlayerJoined);
addEventHandler("onPlayerChat", onPlayerChat);
addEventHandler("onPlayerQuit", onPlayerQuit);
addEventHandler("onElementStreamIn", onElementStreamIn);
addEventHandler("onElementStreamOut", onElementStreamOut);
addEventHandler("onPedSpawn", onPedSpawn);
if (getGame() <= V_GAME_GTA_IV) {
addEventHandler("onPedEnteredVehicleEx", onPedEnteredVehicle);
addEventHandler("onPedExitedVehicleEx", onPedExitedVehicle);
addEventHandler("onPedEnteredSphereEx", onPedEnteredSphere);
addEventHandler("onPedExitedSphereEx", onPedExitedSphere);
}
if (getGame() <= V_GAME_GTA_SA) {
addEventHandler("OnPickupCollected", onPedPickupPickedUp);
}
if (getGame() == V_GAME_MAFIA_ONE) {
addEventHandler("onPedEnteringVehicleEx", onPedEnteredVehicle);
addEventHandler("onPedExitingVehicleEx", onPedExitedVehicle);
}
}
// ===========================================================================
function getVehicleOccupants(vehicle) {
let occupants = [];
let clients = getClients();
for (let i in clients) {
if (getPlayerVehicle(clients[i]) == vehicle) {
occupants.push(clients[i]);
}
}
return occupants;
}
// ===========================================================================

View File

@@ -806,10 +806,10 @@ function disconnectFromDatabase(dbConnection) {
function queryDatabase(dbConnection, queryString, useThread = false) {
logToConsole(LOG_DEBUG, `[V.RP.Database] Query string: ${queryString}`);
if (useThread == true) {
Promise.resolve().then(() => {
let queryResult = dbConnection.query(queryString);
return queryResult;
});
//Promise.resolve().then(() => {
let queryResult = dbConnection.query(queryString);
return queryResult;
//});
} else {
return dbConnection.query(queryString);
}
@@ -857,7 +857,7 @@ function freeDatabaseQuery(dbQuery) {
// ===========================================================================
async function fetchQueryAssoc(dbConnection, queryString) {
function fetchQueryAssoc(dbConnection, queryString) {
return dbConnection.query(queryString, function (err, result, fields) {
return result;
});

View File

@@ -1010,6 +1010,12 @@ function sendPlayerEnterPropertyKey(client, key) {
// ===========================================================================
function sendPlayerScoreBoardKey(client, key) {
sendNetworkEventToPlayer("v.rp.scoreBoardKey", client, key);
}
// ===========================================================================
function makePedPlayAnimation(ped, animationSlot, positionOffset) {
if (getAnimationData(animationSlot).loop == true) {
setEntityData(ped, "v.rp.anim", animationSlot, true);
@@ -1112,8 +1118,8 @@ function setPlayerInfiniteRun(client, state) {
// ==========================================================================
function sendBusinessToPlayer(client, businessId, isDeleted, name, entrancePosition, blipModel, pickupModel, buyPrice, rentPrice, hasInterior, locked, hasItems) {
sendNetworkEventToPlayer("v.rp.business", client, businessId, isDeleted, name, entrancePosition, blipModel, pickupModel, buyPrice, rentPrice, hasInterior, locked, hasItems);
function sendBusinessToPlayer(client, businessId, isDeleted, name, entrancePosition, blipModel, pickupModel, buyPrice, rentPrice, hasInterior, locked, hasItems, entranceFee) {
sendNetworkEventToPlayer("v.rp.business", client, businessId, isDeleted, name, entrancePosition, blipModel, pickupModel, buyPrice, rentPrice, hasInterior, locked, hasItems, entranceFee);
}
// ==========================================================================
@@ -1136,12 +1142,31 @@ function sendVehicleToPlayer(client, vehicleId, isDeleted, model, position, head
// ==========================================================================
function sendPayPhoneToPlayer(client, payPhoneId, isDeleted, state, position) {
sendNetworkEventToPlayer("v.rp.payPhone", client, payPhoneId, isDeleted, state, position);
}
// ==========================================================================
function sendAllBusinessesToPlayer(client) {
sendNetworkEventToPlayer("v.rp.removeBusinesses", client);
let businesses = getServerData().businesses;
for (let i in businesses) {
sendBusinessToPlayer(client, businesses[i].index, false, businesses[i].name, businesses[i].entrancePosition, businesses[i].entranceBlipModel, businesses[i].entrancePickupModel, businesses[i].buyPrice, businesses[i].rentPrice, businesses[i].hasInterior, doesBusinessHaveAnyItemsToBuy(i));
sendBusinessToPlayer(client,
businesses[i].index,
false,
businesses[i].name,
businesses[i].entrancePosition,
businesses[i].entranceBlipModel,
businesses[i].entrancePickupModel,
businesses[i].buyPrice,
businesses[i].rentPrice,
businesses[i].hasInterior,
businesses[i].locked,
doesBusinessHaveAnyItemsToBuy(i),
businesses[i].entranceFee
);
}
}
@@ -1182,6 +1207,17 @@ function sendAllVehiclesToPlayer(client) {
// ==========================================================================
function sendAllPayPhonesToPlayer(client) {
sendNetworkEventToPlayer("v.rp.removePayPhones", client);
let payPhones = getServerData().payPhones;
for (let i in payPhones) {
sendPayPhoneToPlayer(client, payPhones[i].index, false, payPhones[i].state, payPhones[i].position);
}
}
// ==========================================================================
function makePlayerHoldObjectModel(client, modelIndex) {
sendNetworkEventToPlayer("v.rp.holdObject", client, getPlayerData(client).ped, modelIndex);
}
@@ -1302,7 +1338,7 @@ function showSingleParticleEffect(position, particleEffectId, strength = 1.0, du
// ==========================================================================
function sendPlayerCurrencyString(client) {
sendNetworkEventToPlayer("v.rp.currencyString", client, getGlobalConfig().economy.currencyString);
sendNetworkEventToPlayer("v.rp.currencyString", client, getServerConfig().economy.currencyString);
}
// ==========================================================================
@@ -1319,11 +1355,6 @@ function playerMapLoaded(client, mapName) {
setTimeout(function () {
processPlayerEnteringExitingProperty(client);
setTimeout(function () {
logToConsole(LOG_DEBUG, `[V.RP.NetEvents] Enabling all rendering states for ${getPlayerDisplayForConsole(client)} since map switch finished`);
setPlayer2DRendering(client, true, true, true, true, true, true);
}, 500);
}, 500);
}
@@ -1351,4 +1382,34 @@ function requestPlayerToken(client) {
sendNetworkEventToPlayer("v.rp.token", client);
}
// ==========================================================================
function sendPayPhoneStateToPlayer(client, payPhoneIndex, state) {
sendNetworkEventToPlayer("v.rp.payPhoneState", client, payPhoneIndex, state);
}
// ==========================================================================
function sendPayPhoneDialingToPlayer(client) {
sendNetworkEventToPlayer("v.rp.payPhoneDial", client);
}
// ==========================================================================
function sendPayPhoneHangupToPlayer(client) {
sendNetworkEventToPlayer("v.rp.payPhoneHangup", client);
}
// ==========================================================================
function sendPayPhonePickupToPlayer(client) {
sendNetworkEventToPlayer("v.rp.payPhonePickup", client);
}
// ==========================================================================
function sendIncomingDamageMultiplierToClient(client, multiplier) {
sendNetworkEventToPlayer("v.rp.incomingDamageMultiplier", client, multiplier);
}
// ==========================================================================

View File

@@ -519,7 +519,7 @@ function deleteNPCCommand(command, params, client) {
// ===========================================================================
function deleteNPC(npcId) {
quickDatabaseQuery(`DELETE FROM npc_main WHERE npc_id=${getNPCData(npcId).databaseId}`);
quickDatabaseQuery(`UPDATE npc_main SET npc_deleted = 1 WHERE npc_id=${getNPCData(npcId).databaseId}`);
if (getNPCData(npcId)) {
if (getNPCData(npcId).ped != false) {

721
scripts/server/payphone.js Normal file
View File

@@ -0,0 +1,721 @@
// ===========================================================================
// Vortrex's Roleplay Resource
// https://github.com/VortrexFTW/v-roleplay
// ===========================================================================
// FILE: payphone.js
// DESC: Provides payphone functions and commands
// TYPE: Server (JavaScript)
// ===========================================================================
class PayPhoneData {
constructor(dbAssoc = false) {
this.databaseId = 0;
this.serverId = 0;
this.index = -1;
this.state = V_PAYPHONE_STATE_IDLE;
this.number = 0;
this.position = toVector3(0.0, 0.0, 0.0);
this.usingPlayer = false;
this.connectedPlayer = false;
this.enabled = false;
this.broken = false;
this.price = 0;
this.whoAdded = 0;
this.whenAdded = 0;
this.otherPayPhone = -1;
if (dbAssoc) {
this.databaseId = toInteger(dbAssoc["payphone_id"]);
this.serverId = toInteger(dbAssoc["payphone_server"]);
this.number = toInteger(dbAssoc["payphone_number"]);
this.enabled = intToBool(dbAssoc["payphone_enabled"]);
this.broken = intToBool(dbAssoc["payphone_broken"]);
this.position = toVector3(toFloat(dbAssoc["payphone_pos_x"]), toFloat(dbAssoc["payphone_pos_y"]), toFloat(dbAssoc["payphone_pos_z"]));
this.price = toInteger(dbAssoc["payphone_price"]);
this.whoAdded = toInteger(dbAssoc["payphone_who_added"]);
this.whenAdded = toInteger(dbAssoc["payphone_when_added"]);
}
}
};
// ===========================================================================
function initPayPhoneScript() {
logToConsole(LOG_INFO, "[V.RP.PayPhone]: Initializing payphone script ...");
logToConsole(LOG_INFO, "[V.RP.PayPhone]: Payphone script initialized successfully!");
}
// ===========================================================================
function createPayPhoneCommand(command, params, client) {
let payPhoneNumber = generateRandomPhoneNumber();
if (!areParamsEmpty(params)) {
if (isNaN(params)) {
messagePlayerError(client, getLocaleString(client, "MustBeNumber"));
return false;
}
payPhoneNumber = toInteger(params);
}
let closestPayPhone = getClosestPayPhone(getPlayerPosition(client));
if (closestPayPhone != -1) {
if (getDistance(getPlayerPosition(client), getPayPhoneData(closestPayPhone).position) <= getGlobalConfig().payPhoneAnswerDistance) {
messagePlayerError(client, "There is already a payphone at this location!");
return false;
}
}
createPayPhone(getPlayerPosition(client), payPhoneNumber, getPlayerData(client).accountData.databaseId);
messageAdmins(`{adminOrange}${getPlayerName(client)}{MAINCOLOUR} created a payphone with number {ALTCOLOUR}${payPhoneNumber}`);
}
// ===========================================================================
function createPayPhone(position, number, addedBy = defaultNoAccountId) {
let tempPayPhoneData = new PayPhoneData(false);
tempPayPhoneData.number = number;
tempPayPhoneData.position = position;
tempPayPhoneData.state = V_PAYPHONE_STATE_IDLE;
tempPayPhoneData.needsSaved = true;
tempPayPhoneData.whoAdded = addedBy;
tempPayPhoneData.whenAdded = getCurrentUnixTimestamp();
tempPayPhoneData.whoDeleted = defaultNoAccountId;
tempPayPhoneData.whenDeleted = 0;
tempPayPhoneData.enabled = true;
getServerData().payPhones.push(tempPayPhoneData);
setAllPayPhoneIndexes();
saveAllPayPhonesToDatabase();
sendPayPhoneToPlayer(null, getServerData().payPhones.length - 1, false, tempPayPhoneData.state, tempPayPhoneData.position);
return true;
}
// ===========================================================================
function getClosestPayPhone(position) {
let closest = 0;
for (let i in getServerData().payPhones) {
if (getDistance(position, getServerData().payPhones[i].position) < getDistance(position, getServerData().payPhones[closest].position)) {
closest = i;
}
}
return closest;
}
// ===========================================================================
/**
* @param {Number} payPhoneIndex - The data index of the payphone
* @return {PayPhoneData} The payphone's data (class instance)
*/
function getPayPhoneData(payPhoneIndex) {
if (payPhoneIndex == -1) {
return false;
}
if (typeof getServerData().payPhones[payPhoneIndex] != "undefined") {
return getServerData().payPhones[payPhoneIndex];
}
return false;
}
// ===========================================================================
function getPayPhoneNumberCommand(command, params, client) {
let closestPayPhone = getClosestPayPhone(getPlayerPosition(client));
if (closestPayPhone == -1) {
messagePlayerError(client, getLocaleString(client, "NoPayPhoneCloseEnough"));
return false;
}
if (getDistance(getPlayerPosition(client), getPayPhoneData(closestPayPhone).position) > getGlobalConfig().payPhoneAnswerDistance) {
messagePlayerError(client, getLocaleString(client, "NoPayPhoneCloseEnough"));
return false;
}
messagePlayerInfo(client, getLocaleString(client, "ThisPayPhoneNumber", getPayPhoneData(closestPayPhone).number));
}
// ===========================================================================
function deletePayPhoneCommand(command, params, client) {
let payPhoneIndex = getClosestPayPhone(getPlayerPosition(client));
if (!areParamsEmpty(params)) {
payPhoneIndex = getPayPhoneFromParams(params);
}
if (payPhoneIndex == -1) {
messagePlayerError(client, getLocaleString(client, "InvalidPayPhone"));
return false;
}
if (getPayPhoneData(payPhoneIndex) == false) {
messagePlayerError(client, getLocaleString(client, "InvalidPayPhone"));
return false;
}
messagePlayerInfo(client, getLocaleString(client, "PayPhoneDeleted", getPayPhoneData(payPhoneIndex).number));
// Alert player using the phone, if any
if (getPayPhoneData(payPhoneIndex).usingPlayer != false) {
messagePlayerAlert(client, getLocaleString(client, "UsingPayPhoneDeleted"));
}
// Alert player on the other end of the call, if any
if (getPayPhoneData(payPhoneIndex).connectedPlayer != false) {
messagePlayerNormal(getPayPhoneData(payPhoneIndex).connectedPlayer, getLocaleString("PayPhoneRecipientHangup", "0"));
}
stopUsingPayPhone(getPayPhoneData(payPhoneIndex).usingPlayer);
stopUsingPayPhone(getPayPhoneData(payPhoneIndex).connectedPlayer);
quickDatabaseQuery(`UPDATE payphone_main SET payphone_deleted = 1, payphone_who_deleted = ${getPlayerData(client).accountData.databaseId}, payphone_when_deleted = UNIX_TIMESTAMP() WHERE payphone_id = ${getPayPhoneData(payPhoneIndex).databaseId}`);
getServerData().payPhones.splice(payPhoneIndex, 1);
}
// ===========================================================================
function callPayPhoneCommand(command, params, client) {
if (areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
if (getPlayerData(client).usingPayPhone != -1) {
messagePlayerError(client, getLocaleString(client, "AlreadyUsingPayPhone"));
return false;
}
let closestPayPhone = getClosestPayPhone(getPlayerPosition(client));
if (closestPayPhone == -1) {
messagePlayerError(client, getLocaleString(client, "NoPayPhoneCloseEnough"));
return false;
}
if (getDistance(getPlayerPosition(client), getPayPhoneData(closestPayPhone).position) > getGlobalConfig().payPhoneAnswerDistance) {
messagePlayerError(client, getLocaleString(client, "NoPayPhoneCloseEnough"));
return false;
}
// Will work on dual number/player calling param later
//let targetRecipient = getPayPhoneRecipientFromParams(params);
let targetClient = getPlayerFromParams(params);
if (!targetClient) {
messagePlayerError(client, getLocaleString(client, "InvalidPlayer"));
return false;
}
if (getPlayerData(targetClient).usingPayPhone != -1 || isPlayerRestrained(targetClient) || isPlayerSurrendered(targetClient) || isPlayerMuted(targetClient) || !isPlayerSpawned(targetClient)) {
messagePlayerError(client, getLocaleString(client, "UnableToCallPlayer"));
return false;
}
let closestPayPhoneTarget = getClosestPayPhone(getPlayerPosition(targetClient));
if (closestPayPhoneTarget == closestPayPhone) {
messagePlayerError(client, getLocaleString(client, "UnableToCallPlayer"));
return false;
}
getPayPhoneData(closestPayPhone).state = V_PAYPHONE_STATE_CALLING;
getPayPhoneData(closestPayPhone).usingPlayer = client;
sendPayPhonePickupToPlayer(client);
let nearbyPlayers = getPlayersInRange(getPlayerPosition(client), 3);
for (let i in nearbyPlayers) {
sendPayPhonePickupToPlayer(nearbyPlayers[i]);
}
setTimeout(function () {
for (let i in nearbyPlayers) {
sendPayPhoneDialingToPlayer(nearbyPlayers[i]);
}
setTimeout(function () {
getPayPhoneData(closestPayPhoneTarget).state = V_PAYPHONE_STATE_RINGING;
getPayPhoneData(closestPayPhoneTarget).usingPlayer = client;
getPayPhoneData(closestPayPhoneTarget).otherPayPhone = closestPayPhone;
getPayPhoneData(closestPayPhone).otherPayPhone = closestPayPhoneTarget;
getPlayerData(client).usingPayPhone = closestPayPhone;
sendPayPhoneStateToPlayer(null, closestPayPhone, V_PAYPHONE_STATE_CALLING);
sendPayPhoneStateToPlayer(null, closestPayPhoneTarget, V_PAYPHONE_STATE_RINGING);
}, 6000);
}, 1000);
}
// ===========================================================================
function givePayPhoneToPlayerCommand(command, params, client) {
if (getPlayerData(client).usingPayPhone == -1) {
messagePlayerError(client, "NotUsingPayPhone");
return false;
}
let targetClient = getPlayerFromParams(params);
if (!targetClient) {
messagePlayerError(client, getLocaleString(client, "InvalidPlayer"));
return false;
}
if (getDistance(getPlayerPosition(client), getPlayerPosition(targetClient)) >= getGlobalConfig().payPhoneGiveDistance) {
messagePlayerError(client, getLocaleString(client, "NoPlayerCloseEnough"))
return false;
}
let otherClient = getPlayerData(client).payPhoneOtherPlayer;
messagePlayerAlert(otherClient, getLocaleString(otherClient, "PayPhoneOccupantSwitched"));
messagePlayerAlert(targetClient, getLocaleString(targetClient, "PayPhoneReceived", `{ALTCOLOUR}${getCharacterFullName(targetClient)}{MAINCOLOUR}`));
messagePlayerSuccess(client, getLocaleString(client, "PayPhoneGiven", `{ALTCOLOUR}${getCharacterFullName(targetClient)}{MAINCOLOUR}`));
getPlayerData(targetClient).payPhoneCallStart = getPlayerData(client).payPhoneCallStart;
getPlayerData(targetClient).payPhoneOtherPlayer = otherClient;
getPlayerData(targetClient).usingPayPhone = getPlayerData(client).usingPayPhone;
getPlayerData(targetClient).payPhoneInitiatedCall = getPlayerData(client).payPhoneInitiatedCall;
getPlayerData(client).payPhoneCallStart = 0;
getPlayerData(client).payPhoneOtherPlayer = null;
getPlayerData(client).usingPayPhone = -1;
getPlayerData(client).payPhoneInitiatedCall = false;
getPlayerData(otherClient).payPhoneCallStart = getCurrentUnixTimestamp();
getPlayerData(otherClient).payPhoneOtherPlayer = targetClient;
}
// ===========================================================================
function answerPayPhoneCommand(command, params, client) {
//if (areParamsEmpty(params)) {
// messagePlayerSyntax(client, getCommandSyntaxText(command));
// return false;
//}
if (getPlayerData(client).usingPayPhone != -1) {
messagePlayerError(client, getLocaleString(client, "AlreadyUsingPayPhone"));
return false;
}
let closestPayPhone = getClosestPayPhone(getPlayerPosition(client));
if (getDistance(getPlayerPosition(client), getPayPhoneData(closestPayPhone).position) > getGlobalConfig().payPhoneAnswerDistance) {
messagePlayerError(client, getLocaleString(client, "NoPayPhoneCloseEnough"));
return false;
}
if (getPayPhoneData(closestPayPhone).state != V_PAYPHONE_STATE_RINGING) {
messagePlayerError(client, getLocaleString(client, "PayPhoneNotRinging"));
return false;
}
let otherClient = getPayPhoneData(closestPayPhone).usingPlayer;
messagePlayerAlert(otherClient, getLocaleString(client, "PayPhoneRecipientAnswered"));
messagePlayerNormal(client, getLocaleString(client, "PayPhoneAnswered"));
getPlayerData(client).payPhoneCallStart = getCurrentUnixTimestamp();
getPlayerData(client).payPhoneOtherPlayer = otherClient;
getPlayerData(client).usingPayPhone = closestPayPhone;
getPlayerData(otherClient).payPhoneCallStart = getCurrentUnixTimestamp();
getPlayerData(otherClient).payPhoneOtherPlayer = client;
getPayPhoneData(closestPayPhone).state = V_PAYPHONE_STATE_ACTIVE_CALL;
getPayPhoneData(closestPayPhone).usingPlayer = client;
getPayPhoneData(getPlayerData(otherClient).usingPayPhone).state = V_PAYPHONE_STATE_ACTIVE_CALL;
sendPayPhoneStateToPlayer(null, closestPayPhone, V_PAYPHONE_STATE_ACTIVE_CALL);
sendPayPhoneStateToPlayer(null, getPlayerData(otherClient).usingPayPhone, V_PAYPHONE_STATE_ACTIVE_CALL);
let nearbyPlayers = getPlayersInRange(getPlayerPosition(client), 3);
for (let i in nearbyPlayers) {
sendPayPhonePickupToPlayer(nearbyPlayers[i]);
}
}
// ===========================================================================
function hangupPayPhoneCommand(command, params, client) {
//if (areParamsEmpty(params)) {
// messagePlayerSyntax(client, getCommandSyntaxText(command));
// return false;
//}
if (getPlayerData(client).usingPayPhone == -1) {
messagePlayerError(client, getLocaleString(client, "NotUsingPayPhone"));
return false;
}
if (getPayPhoneData(getPlayerData(client).usingPayPhone) == false) {
getPlayerData(client).usingPayPhone = -1
messagePlayerError(client, getLocaleString(client, "InvalidPayPhone"));
return false;
}
let clientPayPhoneIndex = getPlayerData(client).usingPayPhone;
let clientPayPhone = getPayPhoneData(clientPayPhoneIndex);
if (clientPayPhone.state == V_PAYPHONE_STATE_CALLING) {
clientPayPhone.state = V_PAYPHONE_STATE_IDLE;
clientPayPhone.usingPlayer = null;
clientPayPhone.otherPayPhone = -1;
sendPayPhoneStateToPlayer(null, clientPayPhoneIndex, V_PAYPHONE_STATE_IDLE);
let otherPayPhoneIndex = getPayPhoneUsedByPlayer(client);
if (clientPayPhoneIndex != otherPayPhoneIndex) {
getPayPhoneData(otherPayPhoneIndex).state = V_PAYPHONE_STATE_IDLE;
getPayPhoneData(otherPayPhoneIndex).usingPlayer = null;
getPayPhoneData(otherPayPhoneIndex).otherPayPhone = -1;
sendPayPhoneStateToPlayer(null, otherPayPhoneIndex, V_PAYPHONE_STATE_IDLE);
let nearbyPlayers = getPlayersInRange(getPlayerPosition(client), 3);
for (let i in nearbyPlayers) {
sendPayPhoneHangupToPlayer(nearbyPlayers[i]);
}
}
} else if (clientPayPhone.state == V_PAYPHONE_STATE_ACTIVE_CALL) {
let otherClient = getPlayerData(client).payPhoneOtherPlayer;
let otherClientPayPhoneIndex = getPlayerData(otherClient).usingPayPhone;
let otherClientPayPhone = getPayPhoneData(otherClientPayPhoneIndex);
if (getPlayerData(client).payPhoneInitiatedCall == true) {
messagePlayerNormal(client, getLocaleString(client, "PayPhoneRecipientHangup", getPayPhoneCallPrice(clientPayPhoneIndex, getCurrentUnixTimestamp() - getPlayerData(client).payPhoneCallStart)));
takePlayerCash(client, getPayPhoneCallPrice(getCurrentUnixTimestamp() - getPlayerData(client).payPhoneCallStart));
messagePlayerAlert(otherClient, getLocaleString(client, "PayPhoneHangup"));
let nearbyPlayers = getPlayersInRange(getPlayerPosition(client), 3);
for (let i in nearbyPlayers) {
sendPayPhoneHangupToPlayer(nearbyPlayers[i]);
}
nearbyPlayers = getPlayersInRange(getPlayerPosition(otherClient), 3);
for (let i in nearbyPlayers) {
sendPayPhoneHangupToPlayer(nearbyPlayers[i]);
}
} else {
messagePlayerNormal(otherClient, getLocaleString(client, "PayPhoneRecipientHangup", getPayPhoneCallPrice(otherClientPayPhoneIndex, getCurrentUnixTimestamp() - getPlayerData(client).payPhoneCallStart)));
takePlayerCash(otherClient, getPayPhoneCallPrice(getCurrentUnixTimestamp() - getPlayerData(client).payPhoneCallStart));
messagePlayerAlert(client, getLocaleString(client, "PayPhoneHangup"));
}
clientPayPhone.state = V_PAYPHONE_STATE_IDLE;
clientPayPhone.otherPayPhone = -1;
otherClientPayPhone.state = V_PAYPHONE_STATE_IDLE;
otherClientPayPhone.otherPayPhone = -1;
sendPayPhoneStateToPlayer(null, clientPayPhone, V_PAYPHONE_STATE_IDLE);
sendPayPhoneStateToPlayer(null, otherClientPayPhone, V_PAYPHONE_STATE_IDLE);
getPlayerData(otherClient).payPhoneCallStart = 0;
getPlayerData(otherClient).payPhoneOtherPlayer = null;
getPlayerData(otherClient).usingPayPhone = -1;
}
getPlayerData(client).payPhoneCallStart = 0
getPlayerData(client).payPhoneOtherPlayer = null;
getPlayerData(client).usingPayPhone = -1;
}
// ===========================================================================
function loadPayPhonesFromDatabase() {
logToConsole(LOG_DEBUG, `[V.RP.PayPhone]: Loading payphones from database ...`);
let dbConnection = connectToDatabase();
let tempPayPhones = [];
let dbAssoc = [];
if (dbConnection) {
let dbQueryString = `SELECT * FROM payphone_main WHERE payphone_server = ${getServerId()} AND payphone_enabled = 1`;
dbAssoc = fetchQueryAssoc(dbConnection, dbQueryString);
if (dbAssoc.length > 0) {
for (let i in dbAssoc) {
let tempPayPhoneData = new PayPhoneData(dbAssoc[i]);
tempPayPhones.push(tempPayPhoneData);
}
}
disconnectFromDatabase(dbConnection);
}
logToConsole(LOG_DEBUG, `[V.RP.PayPhone]: ${tempPayPhones.length} payphones loaded from database successfully!`);
return tempPayPhones;
}
// ===========================================================================
function saveAllPayPhonesToDatabase() {
if (getServerConfig().devServer) {
return false;
}
for (let i in getServerData().payPhones) {
savePayPhoneToDatabase(i);
}
}
// ===========================================================================
function savePayPhoneToDatabase(payPhoneIndex) {
if (getServerConfig().devServer) {
logToConsole(LOG_VERBOSE, `[V.RP.PayPhone]: Payphone ${payPhoneIndex} can't be saved because server is running as developer only. Aborting save ...`);
return false;
}
if (getPayPhoneData(payPhoneIndex) == false) {
logToConsole(LOG_VERBOSE, `[V.RP.PayPhone]: Payphone ${payPhoneIndex} data is invalid. Aborting save ...`);
return false;
}
let tempPayPhoneData = getPayPhoneData(payPhoneIndex);
if (tempPayPhoneData.databaseId == -1) {
logToConsole(LOG_VERBOSE, `[V.RP.PayPhone]: Payphone ${payPhoneIndex} is a temp payphone. Aborting save ...`);
return false;
}
if (!tempPayPhoneData.needsSaved) {
logToConsole(LOG_VERBOSE, `[V.RP.PayPhone]: Payphone ${payPhoneIndex} hasn't changed data. Aborting save ...`);
return false;
}
logToConsole(LOG_VERBOSE, `[V.RP.PayPhone]: Saving payphone ${tempPayPhoneData.databaseId} to database ...`);
let dbConnection = connectToDatabase();
if (dbConnection) {
let data = [
["payphone_server", getServerId()],
["payphone_number", toInteger(tempPayPhoneData.number)],
["payphone_enabled", boolToInt(tempPayPhoneData.enabled)],
["payphone_price", toInteger(tempPayPhoneData.price)],
["payphone_who_added", toInteger(tempPayPhoneData.whoAdded)],
["payphone_when_added", toInteger(tempPayPhoneData.whenAdded)],
["payphone_pos_x", toFloat(tempPayPhoneData.position.x)],
["payphone_pos_y", toFloat(tempPayPhoneData.position.y)],
["payphone_pos_z", toFloat(tempPayPhoneData.position.z)],
];
let dbQuery = null;
if (tempPayPhoneData.databaseId == 0) {
let queryString = createDatabaseInsertQuery("payphone_main", data);
dbQuery = queryDatabase(dbConnection, queryString);
tempPayPhoneData.databaseId = getDatabaseInsertId(dbConnection);
tempPayPhoneData.needsSaved = false;
} else {
let queryString = createDatabaseUpdateQuery("payphone_main", data, `payphone_id=${tempPayPhoneData.databaseId}`);
dbQuery = queryDatabase(dbConnection, queryString);
getPayPhoneData(payPhoneIndex).needsSaved = false;
}
logToConsole(LOG_VERBOSE, `[V.RP.PayPhone]: Saved payphone ${payPhoneIndex} to database!`);
freeDatabaseQuery(dbQuery);
disconnectFromDatabase(dbConnection);
return true;
}
return false;
}
// ===========================================================================
function setAllPayPhoneIndexes() {
for (let i in getServerData().payPhones) {
getServerData().payPhones[i].index = i;
}
}
// ===========================================================================
function getPayPhoneCallPrice(payPhoneIndex, durationSeconds) {
// Charge price for every 10 seconds
return getPayPhoneData(payPhoneIndex).price * Math.ceil(durationSeconds / 10);
}
// ===========================================================================
function getPayPhoneUsedByPlayer(client) {
for (let i in getServerData().payPhones) {
if (getServerData().payPhones[i].usingPlayer) {
return i;
}
}
return -1;
}
// ===========================================================================
function getNearbyPayPhonesCommand(command, params, client) {
let distance = 10.0;
if (!areParamsEmpty(params)) {
distance = getParam(params, " ", 1);
}
if (isNaN(distance)) {
messagePlayerError(client, "The distance must be a number!");
return false;
}
distance = toFloat(distance);
if (distance <= 0) {
messagePlayerError(client, "The distance must be more than 0!");
return false;
}
let nearbyPayPhones = getPayPhonesInRange(getPlayerPosition(client), distance);
if (nearbyPayPhones.length == 0) {
messagePlayerAlert(client, getLocaleString(client, "NoPayPhonesWithinRange", distance));
return false;
}
let payPhonesList = nearbyPayPhones.map(function (x) {
return `{chatBoxListIndex}${x.index}: {MAINCOLOUR}${x.number} {mediumGrey}(${toFloat(getDistance(getPlayerPosition(client), x.position)).toFixed(2)} ${toLowerCase(getLocaleString(client, "Meters"))} ${toLowerCase(getGroupedLocaleString(client, "CardinalDirections", getCardinalDirectionName(getCardinalDirection(getPlayerPosition(client), x.position))))})`;
});
let chunkedList = splitArrayIntoChunks(payPhonesList, 4);
messagePlayerNormal(client, makeChatBoxSectionHeader(getLocaleString(client, "HeaderPayPhonesInRangeList", `${distance} ${toLowerCase(getLocaleString(client, "Meters"))}`)));
for (let i in chunkedList) {
messagePlayerInfo(client, chunkedList[i].join(", "));
}
}
// ===========================================================================
function getPayPhonesInRange(position, distance) {
return getServerData().payPhones.filter((payPhone) => getDistance(position, payPhone.position) <= distance);
}
// ===========================================================================
function stopUsingPayPhone(client) {
if (client == null) {
return false;
}
if (getPlayerData(client) == false) {
return false;
}
if (getPlayerData(client).usingPayPhone == -1) {
return false;
}
getPayPhoneData(getPlayerData(client).usingPayPhone).state = V_PAYPHONE_STATE_IDLE;
sendPayPhoneStateToPlayer(client, getPlayerData(client).usingPayPhone, V_PAYPHONE_STATE_IDLE);
getPlayerData(client).payPhoneCallStart = 0
getPlayerData(client).payPhoneOtherPlayer = null;
getPlayerData(client).usingPayPhone = -1;
}
// ===========================================================================
/**
* This is a command handler function.
*
* @param {string} command - The command name used by the player
* @param {string} params - The parameters/args string used with the command by the player
* @param {Client} client - The client/player that used the command
* @return {bool} Whether or not the command was successful
*
*/
function getPayPhoneInfoCommand(command, params, client) {
let payPhoneIndex = getClosestPayPhone(getPlayerPosition(client));
if (!areParamsEmpty(params)) {
payPhoneIndex = getPayPhoneFromParams(params);
}
if (!getPayPhoneData(payPhoneIndex)) {
messagePlayerError(client, getLocaleString(client, "InvalidPayPhone"));
return false;
}
let payPhoneData = getPayPhoneData(payPhoneIndex);
let tempStats = [
[`ID`, `${payPhoneData.index}/${payPhoneData.databaseId}`],
[`Number`, `${payPhoneData.number}`],
[`State`, `${getPayPhoneStateName(payPhoneData.state)}`],
[`Added By`, `${loadAccountFromId(payPhoneData.whoAdded).name} on ${new Date(payPhoneData.whenAdded * 1000).toLocaleString()}`],
];
let stats = tempStats.map(stat => `{MAINCOLOUR}${stat[0]}: {ALTCOLOUR}${stat[1]}{MAINCOLOUR}`);
messagePlayerNormal(client, makeChatBoxSectionHeader(getLocaleString(client, "HeaderPayPhoneInfo", payPhoneData.number)));
let chunkedList = splitArrayIntoChunks(stats, 6);
for (let i in chunkedList) {
messagePlayerInfo(client, chunkedList[i].join(", "));
}
}
// ===========================================================================
function resetAllPayPhonesCommand(command, params, client) {
resetAllPayPhones();
}
// ===========================================================================
function resetAllPayPhones() {
for (let i in getServerData().payPhones) {
if (getServerData().payPhones[i].usingPlayer != null) {
getPlayerData(getServerData().payPhones[i].usingPlayer).usingPayPhone = -1;
getPlayerData(getServerData().payPhones[i].usingPlayer).payPhoneCallStart = 0;
getPlayerData(getServerData().payPhones[i].usingPlayer).payPhoneInitiatedCall = false;
getPlayerData(getServerData().payPhones[i].usingPlayer).payPhoneOtherPlayer = null;
}
getServerData().payPhones[i].state = V_PAYPHONE_STATE_IDLE;
}
sendPayPhoneStateToPlayer(null, -1, V_PAYPHONE_STATE_IDLE);
}
// ===========================================================================
function fixDesyncedPayPhones() {
for (let i in getServerData().payPhones) {
switch (getServerData().payPhones[i].state) {
case V_PAYPHONE_STATE_RINGING:
if (getPayPhoneData(i).otherPayPhone != -1) {
if (getPayPhoneData(getPayPhoneData(i).otherPayPhone).state != V_PAYPHONE_STATE_CALLING) {
if (getServerData().payPhones[i].usingPlayer != null) {
getPlayerData(getServerData().payPhones[i].usingPlayer).usingPayPhone = -1;
getPlayerData(getServerData().payPhones[i].usingPlayer).payPhoneCallStart = 0;
getPlayerData(getServerData().payPhones[i].usingPlayer).payPhoneInitiatedCall = false;
getPlayerData(getServerData().payPhones[i].usingPlayer).payPhoneOtherPlayer = null;
}
getPayPhoneData(i).otherPayPhone = -1;
setPayPhoneState(i, V_PAYPHONE_STATE_IDLE);
}
}
break;
default:
break;
}
}
}
// ===========================================================================
function setPayPhoneState(payPhoneIndex, state) {
getPayPhoneData(payPhoneIndex).state = state;
sendPayPhoneStateToPlayer(null, payPhoneIndex, state);
}
// ===========================================================================

View File

@@ -17,6 +17,9 @@ const V_PROMPT_GIVEHOUSETOCLAN = 5;
const V_PROMPT_BUYBIZ = 6;
const V_PROMPT_BUYHOUSE = 7;
const V_PROMPT_RESETKEYBINDS = 8;
const V_PROMPT_RESETACTIONTIPS = 9;
const V_PROMPT_JOBINVITE = 10;
const V_PROMPT_CLANINVITE = 11;
// ===========================================================================
@@ -43,16 +46,7 @@ function playerPromptAnswerNo(client) {
break;
case V_PROMPT_BIZORDER:
if (getPlayerData(client).businessOrderAmount > 0) {
if (doesPlayerUseGUI(client)) {
showPlayerErrorGUI(client, getLocaleString(client, "BusinessOrderCanceled"), getLocaleString(client, "GUIWarning"));
} else {
logToConsole(LOG_DEBUG, `${getPlayerDisplayForConsole(client)} canceled the order of ${getPlayerData(client).businessOrderAmount} ${getPlayerData(client).businessOrderItem} at ${getPlayerData(client).businessOrderCost / getPlayerData(client).businessOrderAmount} each for business ${getBusinessData(getPlayerData(client).businessOrderBusiness)}`);
messagePlayerError(client, getLocaleString(client, "BusinessOrderCanceled"));
}
} else {
showPlayerErrorGUI(client, getLocaleString(client, "NotOrderingAnyBusinessItems"), getLocaleString(client, getLocaleString(client, "GUIWarningTitle")));
}
showPlayerError(client, getLocaleString(client, "BusinessOrderCanceled"), getLocaleString(client, "GUIWarningTitle"));
break;
default:
@@ -83,19 +77,14 @@ function playerPromptAnswerYes(client) {
if (getPlayerData(client).businessOrderAmount > 0) {
if (getBusinessData(getPlayerData(client).businessOrderBusiness).till < getPlayerData(client).businessOrderCost) {
logToConsole(LOG_DEBUG, `[V.RP.Prompt] ${getPlayerDisplayForConsole(client)} failed to order ${getPlayerData(client).businessOrderAmount} ${getItemTypeData(getPlayerData(client).businessOrderItem).name} at ${getPlayerData(client).businessOrderCost / getPlayerData(client).businessOrderAmount} each for business ${getBusinessData(getPlayerData(client).businessOrderBusiness).name} (Reason: Not enough money in business till)`);
if (doesPlayerHaveGUIEnabled(client)) {
showPlayerErrorGUI(client, getLocaleString(client, "BusinessOrderNotEnoughMoney", `{ALTCOLOUR}/bizdeposit{MAINCOLOUR}`), getLocaleString(client, "BusinessOrderCanceled"));
} else {
messagePlayerError(client, getLocaleString(client, "BusinessOrderNotEnoughMoney", `{ALTCOLOUR}/bizdeposit{MAINCOLOUR}`));
}
showPlayerError(client, getLocaleString(client, "BusinessOrderNotEnoughMoney", `{ALTCOLOUR}/bizdeposit{MAINCOLOUR}`), getLocaleString(client, "BusinessOrderCanceled"));
getPlayerData(client).businessOrderAmount = 0;
getPlayerData(client).businessOrderBusiness = false;
getPlayerData(client).businessOrderItem = -1;
getPlayerData(client).businessOrderValue = -1;
} else {
logToConsole(LOG_DEBUG, `[V.RP.Prompt] ${getPlayerDisplayForConsole(client)} successfully ordered ${getPlayerData(client).businessOrderAmount} ${getItemTypeData(getPlayerData(client).businessOrderItem).name} at ${getPlayerData(client).businessOrderCost / getPlayerData(client).businessOrderAmount} each for business ${getBusinessData(getPlayerData(client).businessOrderBusiness).name}`);
showPlayerInfoGUI(client, getLocaleString(client, "BusinessOrderSuccessInfo", getPlayerData(client).businessOrderAmount, getItemTypeData(getPlayerData(client).businessOrderItem).name, getItemValueDisplay(getPlayerData(client).businessOrderItem, getPlayerData(client).businessOrderValue), getPlayerData(client).businessOrderCost), getLocaleString(client, "GUIInfoTitle"));
showPlayerInfo(client, getLocaleString(client, "BusinessOrderSuccessInfo", getPlayerData(client).businessOrderAmount, getItemTypeData(getPlayerData(client).businessOrderItem).name, getItemValueDisplay(getPlayerData(client).businessOrderItem, getPlayerData(client).businessOrderValue), getPlayerData(client).businessOrderCost), getLocaleString(client, "GUIInfoTitle"));
createItem(getPlayerData(client).businessOrderItem, getPlayerData(client).businessOrderValue, V_ITEM_OWNER_BIZFLOOR, getBusinessData(getPlayerData(client).businessOrderBusiness).databaseId, getPlayerData(client).businessOrderAmount);
cacheBusinessItems(getPlayerData(client).businessOrderBusiness);
getBusinessData(getPlayerData(client).businessOrderBusiness).till -= getPlayerData(client).businessOrderCost;
@@ -106,7 +95,7 @@ function playerPromptAnswerYes(client) {
getPlayerData(client).businessOrderValue = -1;
}
} else {
showPlayerErrorGUI(client, ``, `Business Order Canceled`);
showPlayerError(client, getLocaleString(client, "BusinessOrderCanceled"), getLocaleString(client, "GUIWarningTitle"));
}
break;
}
@@ -232,12 +221,13 @@ function playerPromptAnswerYes(client) {
return false;
}
takePlayerCash(client, getBusinessData(businessId).buyPrice);
getBusinessData(businessId).ownerType = V_BIZ_OWNER_PLAYER;
getBusinessData(businessId).ownerId = getPlayerCurrentSubAccount(client).databaseId;
getBusinessData(businessId).buyPrice = 0;
getBusinessData(businessId).needsSaved = true;
updateBusinessPickupLabelData(businessId);
takePlayerCash(client, getBusinessData(businessId).buyPrice);
messageDiscordEventChannel(`🏢 ${getCharacterFullName(client)} is now the owner of *${getBusinessData(businessId).name}*!`);
messagePlayerSuccess(client, getLocaleString(client, "BusinessPurchased", `{businessBlue}${getBusinessData(businessId).name}{MAINCOLOUR}`));
@@ -269,6 +259,20 @@ function playerPromptAnswerYes(client) {
break;
}
case V_PROMPT_RESETACTIONTIPS: {
getPlayerData(client).accountData.seenActionTips = 0;
messagePlayerSuccess(client, getLocaleString(client, "ActionTipsReset"));
break;
}
case V_PROMPT_CLANINVITE: {
break;
}
case V_PROMPT_JOBINVITE: {
break;
}
default: {
messagePlayerError(client, getLocaleString(client, "NoPromptAccept"));
submitBugReport(client, `[AUTOMATED REPORT] Tried to accept invalid prompt type: ${getPlayerData(client).promptType}`);

View File

@@ -7,4 +7,4 @@
// TYPE: Server (JavaScript)
// ===========================================================================
let accountSaltHash = "FGjD49yWqMrW";
// This stuff is in other places, depending on type. I'll probably remove this file soon.

View File

@@ -393,24 +393,37 @@ function getVehicleCommand(command, params, client) {
return false;
}
if (typeof getServerData().vehicles[toInteger(params) - 1] == "undefined") {
let vehicleIndex = toInteger(params);
if (typeof getServerData().vehicles[vehicleIndex] == "undefined") {
messagePlayerError(client, "That vehicle ID doesn't exist!");
}
let vehicle = getServerData().vehicles[toInteger(params) - 1].vehicle;
destroyGameElement(getServerData().vehicles[vehicleIndex]);
getServerData().vehicles[vehicleIndex].vehicle = null;
let oldStreamInDistance = getElementStreamInDistance(vehicle);
let oldStreamOutDistance = getElementStreamOutDistance(vehicle);
getServerData().vehicles[vehicleIndex].spawnPosition = getPlayerPosition(client);
getServerData().vehicles[vehicleIndex].spawnRotation = getPlayerHeading(client);
setElementStreamInDistance(vehicle, 9999999);
setElementStreamOutDistance(vehicle, 9999999 + 1);
//let oldStreamInDistance = getElementStreamInDistance(vehicle);
//let oldStreamOutDistance = getElementStreamOutDistance(vehicle);
setElementPosition(vehicle, getPosInFrontOfPos(getPlayerPosition(client), fixAngle(getPlayerHeading(client)), 5.0));
setElementInterior(vehicle, getPlayerInterior(client));
setElementDimension(vehicle, getPlayerDimension(client));
//setElementStreamInDistance(vehicle, 9999999);
//setElementStreamOutDistance(vehicle, 9999999 + 1);
setElementStreamInDistance(vehicle, oldStreamInDistance);
setElementStreamOutDistance(vehicle, oldStreamOutDistance);
//setElementPosition(vehicle, getPosInFrontOfPos(getPlayerPosition(client), fixAngle(getPlayerHeading(client)), 5.0));
//setElementInterior(vehicle, getPlayerInterior(client));
//setElementDimension(vehicle, getPlayerDimension(client));
//setElementStreamInDistance(vehicle, oldStreamInDistance);
//setElementStreamOutDistance(vehicle, oldStreamOutDistance);
let vehicle = spawnVehicle(getServerData().vehicles[vehicleIndex]);
if (getServerData().vehicles[vehicleIndex].vehicle == null) {
messagePlayerError(client, "Vehicle could not be retrieved!");
return false;
}
messageAdmins(`{adminOrange}${getPlayerName(client)}{MAINCOLOUR} teleported a {vehiclePurple}${getVehicleName(vehicle)}{ALTCOLOUR} (ID ${vehicle.id}){MAINCOLOUR} to their position`, true);
}
@@ -1152,18 +1165,6 @@ function getPlayerStaffFlagsCommand(command, params, client) {
*
*/
function getStaffFlagsCommand(command, params, client) {
if (areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
let targetClient = getParam(params, " ", 1);
if (!targetClient) {
messagePlayerError(client, getLocaleString(client, "InvalidPlayer"));
return false;
}
let chunkedList = splitArrayIntoChunks(getServerBitFlagKeys().staffFlagKeys, 8);
messagePlayerInfo(client, makeChatBoxSectionHeader(getLocaleString(client, "HeaderStaffFlagsList")));
@@ -1386,7 +1387,7 @@ function setPlayerStaffTitleCommand(command, params, client) {
return false;
}
getPlayerData(client).accountData.staffTitle = newTitle;
getPlayerData(targetClient).accountData.staffTitle = newTitle;
messageAdmins(`{adminOrange}${getPlayerName(client)}{MAINCOLOUR} set ${getPlayerName(targetClient)}'s{MAINCOLOUR} staff title to {ALTCOLOUR}${newTitle}`);
}
@@ -1647,6 +1648,10 @@ function forceAccountPasswordResetCommand(command, params, client) {
messagePlayerError(client, getLocaleString(client, "InvalidPlayer"));
return false;
}
getPlayerData(targetClient).passwordResetState = V_RESETPASS_STATE_SETPASS;
hideAllPlayerGUI(targetClient);
showPlayerChangePasswordGUI(targetClient);
}
// ===========================================================================
@@ -1910,4 +1915,77 @@ function showAccountStaffNotesCommand(command, params, client) {
return true;
}
// ===========================================================================
/**
* This is a command handler function.
*
* @param {string} command - The command name used by the player
* @param {string} params - The parameters/args string used with the command by the player
* @param {Client} client - The client/player that used the command
* @return {bool} Whether or not the command was successful
*
*/
function setServerDefaultChatTypeCommand(command, params, client) {
if (areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
switch (toLowerCase(params)) {
case "global":
getServerConfig().normalChatType = V_CHAT_TYPE_GLOBAL;
break;
case "local":
getServerConfig().normalChatType = V_CHAT_TYPE_LOCAL;
break;
case "talk":
getServerConfig().normalChatType = V_CHAT_TYPE_TALK;
break;
case "shout":
getServerConfig().normalChatType = V_CHAT_TYPE_SHOUT;
break;
case "whisper":
getServerConfig().normalChatType = V_CHAT_TYPE_WHISPER;
break;
case "none":
getServerConfig().normalChatType = V_CHAT_TYPE_NONE;
break;
default:
messagePlayerError(client, "That chat type is invalid!")
messagePlayerInfo(client, "Available chat types: global, local, talk, shout, whisper, none");
messagePlayerInfo(client, "Global and local are out-of-character, the rest is in-character");
break;
}
messagePlayerSuccess(client, `You set the server's normal chat type to ${toLowerCase(params)}`);
return true;
}
// ===========================================================================
/**
* This is a command handler function.
*
* @param {string} command - The command name used by the player
* @param {string} params - The parameters/args string used with the command by the player
* @param {Client} client - The client/player that used the command
* @return {bool} Whether or not the command was successful
*
*/
function clearChatCommand(command, params, client) {
if (areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
clearChatBox(null);
}
// ===========================================================================

View File

@@ -7,7 +7,8 @@
// TYPE: Server (JavaScript)
// ===========================================================================
async function initServerScripts() {
function initServerScripts() {
serverStarting = true;
checkForAllRequiredModules();
initDatabaseScript();
@@ -38,10 +39,11 @@ async function initServerScripts() {
initRadioScript();
initLocaleScript();
initCommandScript();
initPayPhoneScript();
// Load config and stuff
loadGlobalConfig();
await loadServerConfig();
loadServerConfig();
applyConfigToServer(getServerConfig());
// Load all the server data
@@ -49,13 +51,14 @@ async function initServerScripts() {
setAllServerDataIndexes();
checkServerGameTime();
spawnAllServerElements();
addAllNetworkEventHandlers();
addAllCommandHandlers();
initAllClients();
initTimers();
serverStartTime = getCurrentUnixTimestamp();
serverStarting = false;
}
// ===========================================================================
@@ -150,6 +153,7 @@ function loadServerDataFromDatabase() {
getServerData().radioStations = loadRadioStationsFromDatabase();
getServerData().gates = loadGatesFromDatabase();
getServerData().jobs = loadJobsFromDatabase();
getServerData().payPhones = loadPayPhonesFromDatabase();
}
getServerData().commands = loadCommands();
@@ -167,6 +171,7 @@ function setAllServerDataIndexes() {
setNPCDataIndexes();
setAllRaceDataIndexes();
setAllRadioStationIndexes();
setAllPayPhoneIndexes();
cacheAllGroundItems();
cacheAllBusinessItems();
cacheAllItemItems();
@@ -193,6 +198,23 @@ function spawnAllServerElements() {
// ===========================================================================
function despawnAllServerElements() {
//despawnAllBusinessPickups();
//despawnAllBusinessBlips();
//despawnAllHousePickups();
//despawnAllHouseBlips();
//despawnAllJobPickups();
//despawnAllJobBlips();
//despawnAllGroundItemObjects();
despawnAllVehicles();
despawnAllNPCs();
// Using client-side spheres since server-side ones don't show on GTAC atm (bug)
//createAllJobRouteLocationMarkers();
}
// ===========================================================================
initServerScripts();
// ===========================================================================

View File

@@ -46,6 +46,8 @@ class SubAccountData {
this.inHouse = 0;
this.inBusiness = 0;
this.accent = "";
this.payDayAmount = 0;
this.scene = "";
this.bodyParts = {
hair: [0, 0],
@@ -95,6 +97,8 @@ class SubAccountData {
this.inHouse = toInteger(dbAssoc["sacct_inhouse"]);
this.inBusiness = toInteger(dbAssoc["sacct_inbusiness"]);
this.accent = toString(dbAssoc["sacct_accent"]);
this.payDayAmount = toInteger(dbAssoc["sacct_svr_payday"]);
this.scene = toString(dbAssoc["sacct_svr_scene"]);
this.bodyParts = {
hair: [toInteger(dbAssoc["sacct_svr_hd_part_hair_model"]) || 0, toInteger(dbAssoc["sacct_svr_hd_part_hair_texture"]) || 0],
@@ -166,6 +170,13 @@ function loadSubAccountFromId(subAccountId) {
// ===========================================================================
/**
* Loads sub accounts (characters) by account ID
*
* @param {Number} accountId - The database ID of the account
* @return {Array.<SubAccountData>} Array of subaccounts that belong to the account ID
*
*/
function loadSubAccountsFromAccount(accountId) {
let tempSubAccounts = [];
let dbAssoc = false;
@@ -246,6 +257,13 @@ function loadSubAccountsFromAccount(accountId) {
// ===========================================================================
/**
* Saves the subaccount data to the database (character)
*
* @param {SubAccountData} subAccountData - The data of the subaccount
* @return {void}
*
*/
function saveSubAccountToDatabase(subAccountData) {
let dbConnection = connectToDatabase();
@@ -284,7 +302,7 @@ function saveSubAccountToDatabase(subAccountData) {
//["sacct_svr_svr", getServerId()],
["sacct_svr_sacct", subAccountData.databaseId],
["sacct_svr_job", subAccountData.job],
//["sacct_svr_job_rank", getServerId()],
["sacct_svr_job_rank", subAccountData.jobRank],
["sacct_svr_clan", subAccountData.clan],
["sacct_svr_clan_rank", subAccountData.clanRank],
["sacct_svr_clan_tag", safeClanTag],
@@ -324,6 +342,7 @@ function saveSubAccountToDatabase(subAccountData) {
["sacct_svr_hd_prop_leftfoot_texture", subAccountData.bodyProps.leftFoot[1]],
["sacct_svr_hd_prop_rightfoot_model", subAccountData.bodyProps.rightFoot[0]],
["sacct_svr_hd_prop_rightfoot_texture", subAccountData.bodyProps.rightFoot[1]],
["sacct_svr_payday", subAccountData.payDayAmount],
];
dbQuery = null;
@@ -338,6 +357,13 @@ function saveSubAccountToDatabase(subAccountData) {
// ===========================================================================
/**
* Creates a new subaccount (character)
*
* @param {SubAccountData} subAccountData - The data of the subaccount
* @return {SubAccountData} The new sub account data
*
*/
function createSubAccount(accountId, firstName, lastName) {
logToConsole(LOG_DEBUG, `[V.RP.Account] Attempting to create subaccount ${firstName} ${lastName} in database`);
@@ -515,6 +541,8 @@ function selectCharacter(client, characterId = -1) {
//setPlayerCameraLookAt(client, getPosBehindPos(spawnPosition, spawnHeading, 5), spawnPosition);
getPlayerData(client).pedState = V_PEDSTATE_SPAWNING;
getPlayerData(client).scene = getPlayerCurrentSubAccount(client).scene;
if (getGame() <= V_GAME_GTA_IV_EFLC) {
spawnPlayer(client, spawnPosition, spawnHeading, getGameConfig().skins[getGame()][skin][0], spawnInterior, spawnDimension);
onPlayerSpawn(client);
@@ -725,7 +753,11 @@ function forcePlayerIntoSwitchCharacterScreen(client) {
getPlayerData(client).switchingCharacter = true;
showConnectCameraToPlayer(client);
despawnPlayer(client);
if (getGame() != V_GAME_MAFIA_ONE) {
showConnectCameraToPlayer(client);
}
showCharacterSelectToClient(client);
}

View File

@@ -43,6 +43,7 @@ function saveServerDataToDatabase() {
}
try {
updateVehicleSavedPositions();
saveAllVehiclesToDatabase();
} catch (error) {
logToConsole(LOG_ERROR, `Could not save vehicles to database: ${error}`);
@@ -78,6 +79,12 @@ function saveServerDataToDatabase() {
logToConsole(LOG_ERROR, `Could not save gates to database: ${error}`);
}
try {
saveAllPayPhonesToDatabase();
} catch (error) {
logToConsole(LOG_ERROR, `Could not save payphones to database: ${error}`);
}
try {
saveServerConfigToDatabase();
} catch (error) {
@@ -113,6 +120,9 @@ function oneMinuteTimerFunction() {
logToConsole(LOG_DEBUG, `[V.RP.Event] Updating all player name tags`);
updateAllPlayerNameTags();
}
updateVehicleSavedPositions();
fixDesyncedPayPhones();
}
// ===========================================================================
@@ -121,7 +131,6 @@ function tenMinuteTimerFunction() {
//showRandomTipToAllPlayers();
//saveServerDataToDatabase();
//checkInactiveVehicleRespawns();
updateVehicleSavedPositions();
}
// ===========================================================================
@@ -236,44 +245,50 @@ function checkServerGameTime() {
if (getGame() == V_GAME_MAFIA_ONE) {
if (getGameConfig().mainWorldScene[getGame()] == "FREERIDE") {
if (isServerGoingToChangeMapsSoon(getServerConfig().hour, getServerConfig().minute)) {
sendMapChangeWarningToPlayer(null, true);
}
//if (isServerGoingToChangeMapsSoon(getServerConfig().hour, getServerConfig().minute)) {
// sendMapChangeWarningToPlayer(null, true);
//}
if (isNightTime(getServerConfig().hour)) {
getGameConfig().mainWorldScene[getGame()] = "FREERIDENOC";
removeAllPlayersFromProperties();
removeAllPlayersFromVehicles();
saveServerDataToDatabase();
logToConsole(LOG_INFO | LOG_WARN, `[V.RP.Timers] Changing server map to night`);
messageDiscordEventChannel("🌙 Changing server map to night");
despawnAllVehicles();
despawnAllNPCs();
despawnAllGroundItemObjects();
getGameConfig().mainWorldScene[getGame()] = "FREERIDENOC";
setServerPassword(generateRandomString(10, getGlobalConfig().alphaNumericCharacters));
if (!serverStarting) {
kickAllClients();
saveServerDataToDatabase();
despawnAllServerElements();
}
game.changeMap(getGameConfig().mainWorldScene[getGame()]);
spawnAllVehicles();
spawnAllNPCs();
spawnAllGroundItemObjects();
spawnAllServerElements();
setServerPassword("");
} else {
if (serverStarting) {
spawnAllServerElements();
}
}
} else if (getGameConfig().mainWorldScene[getGame()] == "FREERIDENOC") {
if (isServerGoingToChangeMapsSoon(getServerConfig().hour, getServerConfig().minute)) {
sendMapChangeWarningToPlayer(null, true);
}
//if (isServerGoingToChangeMapsSoon(getServerConfig().hour, getServerConfig().minute)) {
// sendMapChangeWarningToPlayer(null, true);
//}
if (!isNightTime(getServerConfig().hour)) {
getGameConfig().mainWorldScene[getGame()] = "FREERIDE";
removeAllPlayersFromProperties();
removeAllPlayersFromVehicles();
saveServerDataToDatabase();
logToConsole(LOG_INFO | LOG_WARN, `[V.RP.Timers] Changing server map to day`);
messageDiscordEventChannel("🌞 Changing server map to day");
despawnAllVehicles();
despawnAllNPCs();
despawnAllGroundItemObjects();
getGameConfig().mainWorldScene[getGame()] = "FREERIDE";
setServerPassword(generateRandomString(10, getGlobalConfig().alphaNumericCharacters));
if (!serverStarting) {
kickAllClients();
saveServerDataToDatabase();
despawnAllServerElements();
}
game.changeMap(getGameConfig().mainWorldScene[getGame()]);
spawnAllVehicles();
spawnAllNPCs();
spawnAllGroundItemObjects();
spawnAllServerElements();
setServerPassword("");
} else {
if (serverStarting) {
spawnAllServerElements();
}
}
}
}
@@ -310,7 +325,12 @@ function checkPayDays() {
for (let i in getServerData().businesses) {
if (getBusinessData(i).ownerType != V_BIZ_OWNER_NONE && getBusinessData(i).ownerType != V_BIZ_OWNER_PUBLIC && getBusinessData(i).ownerType != V_BIZ_OWNER_FACTION) {
getBusinessData(i).till += 1000;
let addToTill = getServerConfig().economy.passiveIncomePerPayDay;
if (isDoubleBonusActive()) {
addToTill = addToTill * 2;
}
getBusinessData(i).till = getBusinessData(i).till + addToTill;
getBusinessData(i).needsSaved = true;
}
}
}

View File

@@ -542,109 +542,143 @@ function processPlayerEnteringExitingProperty(client) {
}
if (pedState == V_PEDSTATE_ENTERINGPROPERTY) {
logToConsole(LOG_VERBOSE, `[V.RP.Utilities]: Processing property ENTER for player ${getPlayerDisplayForConsole(client)} ...`);
logToConsole(LOG_DEBUG, `[V.RP.Utilities]: Processing property ENTER for player ${getPlayerDisplayForConsole(client)} ...`);
if (isGameFeatureSupported("interiorScene") && propertyData.exitScene != "") {
logToConsole(LOG_VERBOSE, `[V.RP.Utilities]: Player ${getPlayerDisplayForConsole(client)} is entering a property with interior scene (${propertyData.exitScene})`);
logToConsole(LOG_DEBUG, `[V.RP.Utilities]: Player ${getPlayerDisplayForConsole(client)} is entering a property with interior scene (${propertyData.exitScene}). Spawning ...`);
spawnPlayer(client, propertyData.exitPosition, propertyData.exitRotation, getGameConfig().skins[getGame()][getPlayerCurrentSubAccount(client).skin][0]);
onPlayerSpawn(client);
getPlayerData(client).scene = propertyData.exitScene;
//onPlayerSpawn(client);
setPlayerControlState(client, false);
} else {
setPlayerPosition(client, propertyData.exitPosition);
setPlayerHeading(client, propertyData.exitRotation);
}
if (isGameFeatureSupported("dimension")) {
setPlayerDimension(client, propertyData.exitDimension);
}
if (isGameFeatureSupported("interior")) {
setPlayerInterior(client, propertyData.exitInterior);
}
setTimeout(function () {
if (isFadeCameraSupported()) {
logToConsole(LOG_DEBUG, `[V.RP.Utilities]: Fading camera OUT for player ${getPlayerDisplayForConsole(client)}`);
fadePlayerCamera(client, true, 1000);
}
logToConsole(LOG_DEBUG, `[V.RP.Utilities]: Setting interior lights ${getOnOffFromBool(propertyData.interiorLights)} for player ${getPlayerDisplayForConsole(client)}`);
updateInteriorLightsForPlayer(client, propertyData.interiorLights);
let radioStationIndex = propertyData.streamingRadioStationIndex;
if (radioStationIndex != -1) {
if (getRadioStationData(radioStationIndex)) {
logToConsole(LOG_DEBUG, `[V.RP.Utilities]: Player ${getPlayerDisplayForConsole(client)} entered a property with a radio station set, changing their stream`);
playRadioStreamForPlayer(client, getRadioStationData(radioStationIndex).url);
getPlayerData(client).streamingRadioStation = radioStationIndex;
}
}
}, 1000);
if (getPlayerData(client).enteringExitingProperty[0] == V_PROPERTY_TYPE_BUSINESS) {
if (propertyData.type == V_BIZ_TYPE_PAINTBALL) {
logToConsole(LOG_DEBUG, `[V.RP.Utilities]: Starting paintball for player ${getOnOffFromBool(inProperty.interiorLights)}`);
startPaintBall(client);
}
}
let radioStationIndex = propertyData.streamingRadioStationIndex;
if (radioStationIndex != -1) {
if (getRadioStationData(radioStationIndex)) {
playRadioStreamForPlayer(client, getRadioStationData(radioStationIndex).url);
getPlayerData(client).streamingRadioStation = radioStationIndex;
}
if (isGameFeatureSupported("dimension")) {
logToConsole(LOG_DEBUG, `[V.RP.Utilities]: Setting dimension for player ${getPlayerDisplayForConsole(client)} to ${propertyData.exitDimension}`);
setPlayerDimension(client, propertyData.exitDimension);
}
if (isGameFeatureSupported("interior")) {
logToConsole(LOG_DEBUG, `[V.RP.Utilities]: Setting interior for player ${getPlayerDisplayForConsole(client)} to ${propertyData.exitInterior}`);
setPlayerInterior(client, propertyData.exitInterior);
}
getPlayerData(client).inProperty = [getPlayerData(client).enteringExitingProperty[0], getPlayerData(client).enteringExitingProperty[1]];
getPlayerData(client).enteringExitingProperty = null;
getPlayerData(client).pedState = V_PEDSTATE_READY;
setTimeout(function () {
logToConsole(LOG_DEBUG, `[V.RP.NetEvents] Enabling all rendering states for player ${getPlayerDisplayForConsole(client)} since map switch finished`);
setPlayer2DRendering(client, true, true, true, true, true, true);
setPlayerControlState(client, true);
}, 2500);
} else if (pedState == V_PEDSTATE_EXITINGPROPERTY) {
logToConsole(LOG_VERBOSE, `[V.RP.Utilities]: Processing property EXIT for player ${getPlayerDisplayForConsole(client)} from property ID ${propertyData.index}/${propertyData.databaseId} ...`);
logToConsole(LOG_DEBUG, `[V.RP.Utilities]: Processing property EXIT for player ${getPlayerDisplayForConsole(client)} from property ID ${propertyData.index}/${propertyData.databaseId} ...`);
if (isGameFeatureSupported("interiorScene") && propertyData.entranceScene != "") {
logToConsole(LOG_VERBOSE, `[V.RP.Utilities]: Player ${getPlayerDisplayForConsole(client)} is exiting a property with external interior scene (${propertyData.entranceScene})`);
logToConsole(LOG_DEBUG, `[V.RP.Utilities]: Player ${getPlayerDisplayForConsole(client)} is exiting a property with external interior scene (${propertyData.entranceScene})`);
spawnPlayer(client, propertyData.entrancePosition, propertyData.entranceRotation, getGameConfig().skins[getGame()][getPlayerCurrentSubAccount(client).skin][0]);
onPlayerSpawn(client);
getPlayerData(client).scene = propertyData.entranceScene;
//onPlayerSpawn(client);
setPlayerControlState(client, false);
} else {
setPlayerPosition(client, propertyData.entrancePosition);
setPlayerHeading(client, propertyData.entranceRotation);
}
if (isGameFeatureSupported("dimension")) {
setPlayerDimension(client, propertyData.entranceDimension);
}
if (isGameFeatureSupported("interior")) {
setPlayerInterior(client, propertyData.entranceInterior);
}
// Check if exiting property was into another house/business
let inProperty = false;
let inPropertyType = V_PROPERTY_TYPE_NONE;
let inBusiness = getPlayerBusiness(client);
if (inBusiness != -1) {
inProperty = getBusinessData(inBusiness);
inPropertyType = V_PROPERTY_TYPE_BUSINESS;
} else {
let inHouse = getPlayerHouse(client);
if (inHouse != -1) {
inProperty = getHouseData(inHouse);
inPropertyType = V_PROPERTY_TYPE_HOUSE;
if (getPlayerDimension(client) != getGameConfig().mainWorldDimension[getGame()]) {
let inBusiness = getPlayerBusiness(client);
if (inBusiness != -1) {
inProperty = getBusinessData(inBusiness);
inPropertyType = V_PROPERTY_TYPE_BUSINESS;
} else {
let inHouse = getPlayerHouse(client);
if (inHouse != -1) {
inProperty = getHouseData(inHouse);
inPropertyType = V_PROPERTY_TYPE_HOUSE;
}
}
}
setTimeout(function () {
if (getGame() != V_GAME_MAFIA_ONE && getGame() != V_GAME_GTA_IV) {
if (isFadeCameraSupported()) {
logToConsole(LOG_DEBUG, `[V.RP.Utilities]: Fading camera IN for player ${getPlayerDisplayForConsole(client)}`);
fadePlayerCamera(client, true, 1000);
}
}
logToConsole(LOG_DEBUG, `[V.RP.Utilities]: Setting interior lights ${getOnOffFromBool(inProperty.interiorLights)} for player ${getPlayerDisplayForConsole(client)}`);
updateInteriorLightsForPlayer(client, (inProperty != false) ? inProperty.interiorLights : true);
}, 1000);
logToConsole(LOG_DEBUG, `[V.RP.Utilities]: Attempting to stop paintball for player ${getOnOffFromBool(inProperty.interiorLights)}`);
stopPaintBall(client);
if (inProperty != false) {
if (getBusinessData(inBusiness).streamingRadioStationIndex != -1) {
if (getRadioStationData(getBusinessData(inBusiness).streamingRadioStationIndex)) {
playRadioStreamForPlayer(client, getRadioStationData(getBusinessData(inBusiness).streamingRadioStationIndex).url);
getPlayerData(client).streamingRadioStation = getBusinessData(inBusiness).streamingRadioStationIndex;
logToConsole(LOG_DEBUG, `[V.RP.Utilities]: Player ${getPlayerDisplayForConsole(client)} exited property into another property, changing radio station`);
if (inProperty.streamingRadioStationIndex != -1) {
if (getRadioStationData(inProperty.streamingRadioStationIndex)) {
playRadioStreamForPlayer(client, getRadioStationData(inProperty.streamingRadioStationIndex).url);
getPlayerData(client).streamingRadioStation = inProperty.streamingRadioStationIndex;
}
}
} else {
logToConsole(LOG_DEBUG, `[V.RP.Utilities]: Player ${getPlayerDisplayForConsole(client)} exited property into main world, stopping radio station`);
stopRadioStreamForPlayer(client);
getPlayerData(client).streamingRadioStation = -1;
}
if (isGameFeatureSupported("dimension")) {
logToConsole(LOG_DEBUG, `[V.RP.Utilities]: Setting dimension for player ${getPlayerDisplayForConsole(client)} to ${propertyData.entranceDimension}`);
setPlayerDimension(client, propertyData.entranceDimension);
}
if (isGameFeatureSupported("interior")) {
logToConsole(LOG_DEBUG, `[V.RP.Utilities]: Setting interior for player ${getPlayerDisplayForConsole(client)} to ${propertyData.entranceInterior}`);
setPlayerInterior(client, propertyData.entranceInterior);
}
getPlayerData(client).inProperty = [inPropertyType, inProperty.index];
getPlayerData(client).enteringExitingProperty = null;
getPlayerData(client).pedState = V_PEDSTATE_READY;
setTimeout(function () {
logToConsole(LOG_DEBUG, `[V.RP.NetEvents] Enabling all rendering states for player ${getPlayerDisplayForConsole(client)} since map switch finished`);
setPlayer2DRendering(client, true, true, true, true, true, true);
setPlayerControlState(client, true);
}, 2500);
}
}

View File

@@ -90,6 +90,11 @@ class VehicleData {
this.lastActiveTime = false;
this.rank = 0;
this.whoAdded = 0;
this.whenAdded = 0;
if (dbAssoc) {
// General Info
this.databaseId = toInteger(dbAssoc["veh_id"]);
@@ -154,16 +159,9 @@ class VehicleData {
this.whoAdded = toInteger(dbAssoc["veh_who_added"]);
this.whenAdded = toInteger(dbAssoc["veh_when_added"]);
this.licensePlate = toInteger(dbAssoc["veh_license_plate"]);
this.rank = toInteger(dbAssoc["veh_rank"]);
}
}
saveToDatabase() {
saveVehicleToDatabase(this);
}
respawn() {
respawnVehicle(this.vehicle);
}
};
// ===========================================================================
@@ -186,7 +184,7 @@ function loadVehiclesFromDatabase() {
dbAssoc = fetchQueryAssoc(dbConnection, dbQueryString);
if (dbAssoc.length > 0) {
for (let i in dbAssoc) {
let tempVehicleData = new VehicleData(dbAssoc[i]);
let tempVehicleData = new VehicleData(dbAssoc[i], false);
tempVehicles.push(tempVehicleData);
}
}
@@ -294,6 +292,7 @@ function saveVehicleToDatabase(vehicleDataId) {
["veh_int", toInteger(tempVehicleData.interior)],
["veh_vw", toInteger(tempVehicleData.dimension)],
["veh_livery", toInteger(tempVehicleData.livery)],
["veh_rank", toInteger(tempVehicleData.rank)],
["veh_radio_station", (getRadioStationData(tempVehicleData.streamingRadioStationIndex) != false) ? toInteger(getRadioStationData(tempVehicleData.streamingRadioStationIndex).databaseId) : -1],
];
@@ -322,9 +321,10 @@ function saveVehicleToDatabase(vehicleDataId) {
function spawnAllVehicles() {
for (let i in getServerData().vehicles) {
let vehicle = spawnVehicle(getServerData().vehicles[i]);
getServerData().vehicles[i].vehicle = vehicle;
setEntityData(vehicle, "v.rp.dataSlot", i, false);
if (getServerData().vehicles[i].vehicle == false) {
let vehicle = spawnVehicle(getServerData().vehicles[i]);
getServerData().vehicles[i].vehicle = vehicle;
}
}
setAllVehicleIndexes();
}
@@ -337,9 +337,10 @@ function spawnAllVehicles() {
*/
function getVehicleData(vehicle) {
if (isVehicleObject(vehicle)) {
let dataIndex = getEntityData(vehicle, "v.rp.dataSlot");
if (typeof getServerData().vehicles[dataIndex] != "undefined") {
return getServerData().vehicles[dataIndex];
for (let i in getServerData().vehicles) {
if (getServerData().vehicles[i].vehicle == vehicle) {
return getServerData().vehicles[i];
}
}
}
@@ -367,7 +368,7 @@ function createVehicleCommand(command, params, client) {
}
let frontPos = getPosInFrontOfPos(getPlayerPosition(client), getPlayerHeading(client), getGlobalConfig().spawnCarDistance);
let vehicle = createPermanentVehicle(modelIndex, frontPos, heading, getPlayerInterior(client), getPlayerDimension(client));
let vehicle = createPermanentVehicle(modelIndex, frontPos, heading, getPlayerInterior(client), getPlayerDimension(client), getPlayerData(client).accountData.databaseId);
messageAdmins(`{adminOrange}${getPlayerName(client)}{MAINCOLOUR} created a {vehiclePurple}${getVehicleName(vehicle)}`, true);
}
@@ -388,7 +389,7 @@ function createTemporaryVehicleCommand(command, params, client) {
}
let frontPos = getPosInFrontOfPos(getPlayerPosition(client), getPlayerHeading(client), getGlobalConfig().spawnCarDistance);
let vehicle = createTemporaryVehicle(modelIndex, frontPos, getPlayerHeading(client), getPlayerInterior(client), getPlayerDimension(client));
let vehicle = createTemporaryVehicle(modelIndex, frontPos, getPlayerHeading(client), getPlayerInterior(client), getPlayerDimension(client), getPlayerData(client).accountData.databaseId);
messageAdmins(`{adminOrange}${getPlayerName(client)}{MAINCOLOUR} created a temporary {vehiclePurple}${getVehicleName(vehicle)}`, true);
}
@@ -496,13 +497,18 @@ function deleteVehicleCommand(command, params, client) {
vehicle = getPlayerVehicle(client);
}
let dataIndex = getEntityData(vehicle, "v.rp.dataSlot");
let vehicleIndex = getVehicleData(vehicle).index;
let vehicleName = getVehicleName(vehicle);
quickDatabaseQuery(`UPDATE veh_main SET veh_deleted = 1 WHERE veh_id = ${getVehicleData(vehicle).databaseId}`);
if (getVehicleData(vehicle).databaseId > 0) {
quickDatabaseQuery(`UPDATE veh_main SET veh_deleted = 1 WHERE veh_id = ${getVehicleData(vehicle).databaseId}`);
}
getServerData().vehicles.splice(dataIndex, 1);
destroyElement(vehicle);
getServerData().vehicles.splice(vehicleIndex, 1);
destroyGameElement(vehicle);
setAllVehicleIndexes();
messagePlayerSuccess(client, `The ${vehicleName} has been deleted!`);
}
@@ -818,23 +824,25 @@ function doesPlayerHaveVehicleKeys(client, vehicle) {
if (vehicleData.ownerType == V_VEHOWNER_CLAN) {
if (vehicleData.ownerId == getPlayerCurrentSubAccount(client).clan) {
if (vehicleData.clanRank <= getPlayerCurrentSubAccount(client).clanRank) {
if (getClanRankData(getPlayerClan(client), getPlayerClanRank(client)).level >= vehicleData.rank) {
return true;
}
}
}
if (vehicleData.ownerType == V_VEHOWNER_FACTION) {
if (vehicleData.ownerId == getPlayerCurrentSubAccount(client).faction) {
if (vehicleData.factionRank <= getPlayerCurrentSubAccount(client).factionRank) {
return true;
}
}
}
//if (vehicleData.ownerType == V_VEHOWNER_FACTION) {
// if (vehicleData.ownerId == getPlayerCurrentSubAccount(client).faction) {
// if (vehicleData.factionRank <= getPlayerCurrentSubAccount(client).factionRank) {
// return true;
// }
// }
//}
if (vehicleData.ownerType == V_VEHOWNER_JOB) {
if (vehicleData.ownerId == getPlayerCurrentSubAccount(client).job) {
return true;
if (getJobRankData(getPlayerJob(client), getPlayerJobRank(client)).level >= vehicleData.rank) {
return true;
}
}
}
@@ -928,8 +936,13 @@ function setVehicleRankCommand(command, params, client) {
return false;
}
if (isNaN(params)) {
messagePlayerError(client, getLocaleString(client, "MustBeNumber"));
return false;
}
let vehicle = getPlayerVehicle(client);
let rankId = params;
let level = toInteger(params);
if (!getVehicleData(vehicle)) {
messagePlayerError(client, getLocaleString(client, "RandomVehicleCommandsDisabled"));
@@ -937,16 +950,11 @@ function setVehicleRankCommand(command, params, client) {
}
if (getVehicleData(vehicle).ownerType == V_VEHOWNER_CLAN) {
rankId = getClanRankFromParams(getVehicleData(vehicle).ownerId, params);
if (!getClanRankData(getVehicleData(vehicle).ownerId, rankId)) {
messagePlayerError(client, getLocaleString(client, "InvalidClanRank"));
return false;
}
getVehicleData(vehicle).rank = getClanRankData(getVehicleData(vehicle).ownerId, rankId).databaseId;
messageAdmins(`{adminOrange}${getPlayerName(client)}{MAINCOLOUR} set their {vehiclePurple}${getVehicleName(vehicle)}{MAINCOLOUR} minimum rank to {ALTCOLOUR}${getClanRankData(getVehicleData(vehicle).ownerId, rankId).name}{MAINCOLOUR} of the {clanOrange}${getClanData(getVehicleData(vehicle).ownerId).name}{MAINCOLOUR} clan!`, true);
getVehicleData(vehicle).rank = level
messageAdmins(`{adminOrange}${getPlayerName(client)}{MAINCOLOUR} set their {vehiclePurple}${getVehicleName(vehicle)}{MAINCOLOUR} minimum rank to {ALTCOLOUR}${level}{MAINCOLOUR} of the {clanOrange}${getClanData(getVehicleData(vehicle).ownerId).name}{MAINCOLOUR} clan!`, true);
} else if (getVehicleData(vehicle).ownerType == V_VEHOWNER_JOB) {
getVehicleData(vehicle).rank = rankId;
messageAdmins(`{adminOrange}${getPlayerName(client)}{MAINCOLOUR} set their {vehiclePurple}${getVehicleName(vehicle)}{MAINCOLOUR} minimum rank to {ALTCOLOUR}${rankId}{MAINCOLOUR} of the {jobYellow}${getJobData(getJobIdFromDatabaseId(getVehicleData(vehicle).ownerId)).name}{MAINCOLOUR} job!`, true);
getVehicleData(vehicle).rank = level;
messageAdmins(`{adminOrange}${getPlayerName(client)}{MAINCOLOUR} set their {vehiclePurple}${getVehicleName(vehicle)}{MAINCOLOUR} minimum rank to {ALTCOLOUR}${level}{MAINCOLOUR} of the {jobYellow}${getJobData(getJobIdFromDatabaseId(getVehicleData(vehicle).ownerId)).name}{MAINCOLOUR} job!`, true);
}
getVehicleData(vehicle).needsSaved = true;
@@ -1227,6 +1235,9 @@ function getVehicleInfoCommand(command, params, client) {
[`License Plate`, `${vehicleData.licensePlate}`],
[`Colour`, `${getVehicleColourInfoString(vehicleData.colour1, vehicleData.colour1IsRGBA)}, ${getVehicleColourInfoString(vehicleData.colour1, vehicleData.colour1IsRGBA)}`],
[`Last Driver`, `${vehicleData.lastDriverName}`],
[`Added By`, `${loadAccountFromId(vehicleData.whoAdded).name}`],
[`Added On`, `${new Date(vehicleData.whenAdded).toLocaleDateString("en-GB")}`],
[`Rank Level`, `${vehicleData.rank}`],
];
let stats = tempStats.map(stat => `{chatBoxListIndex}${stat[0]}: {ALTCOLOUR}${stat[1]}{MAINCOLOUR}`);
@@ -1319,14 +1330,10 @@ function toggleVehicleSpawnLockCommand(command, params, client) {
// ===========================================================================
function reloadAllVehiclesCommand(command, params, client) {
for (let i in getServerData().vehicles) {
if (getServerData().vehicles[i].vehicle) {
deleteGameElement(getServerData().vehicles[i].vehicle);
}
}
despawnAllVehicles();
clearArray(getServerData().vehicles);
getServerData().vehicles = loadVehiclesFromDatabase();
setAllVehicleIndexes();
spawnAllVehicles();
announceAdminAction(`AllVehiclesReloaded`);
@@ -1359,10 +1366,10 @@ function respawnAllVehiclesCommand(command, params, client) {
respawnVehicle(getServerData().vehicles[i].vehicle);
}
let randomVehicles = getElementsByType(ELEMENT_VEHICLE).filter(v => getVehicleData(v) == false);
for (let i in randomVehicles) {
destroyElement(randomVehicles[i]);
}
//let randomVehicles = getElementsByType(ELEMENT_VEHICLE).filter(v => getVehicleData(v) == false);
//for (let i in randomVehicles) {
// destroyElement(randomVehicles[i]);
//}
setAllVehicleIndexes();
@@ -1373,17 +1380,19 @@ function respawnAllVehiclesCommand(command, params, client) {
function respawnEmptyVehiclesCommand(command, params, client) {
for (let i in getServerData().vehicles) {
if (!isVehicleUnoccupied(getServerData().vehicles[i].vehicle)) {
if (isVehicleUnoccupied(getServerData().vehicles[i].vehicle)) {
respawnVehicle(getServerData().vehicles[i].vehicle);
}
}
let clientVehicles = getElementsByType(ELEMENT_VEHICLE).filter(v => getVehicleData(v) == false);
for (let i in clientVehicles) {
if (!isVehicleUnoccupied(clientVehicles[i])) {
destroyElement(clientVehicles[i]);
}
}
//let clientVehicles = getElementsByType(ELEMENT_VEHICLE).filter(v => getVehicleData(v) == false);
//for (let i in clientVehicles) {
// if (!isVehicleUnoccupied(clientVehicles[i])) {
// destroyElement(clientVehicles[i]);
// }
//}
setAllVehicleIndexes();
announceAdminAction(`EmptyVehiclesRespawned`);
}
@@ -1397,6 +1406,8 @@ function respawnJobVehiclesCommand(command, params, client) {
}
}
setAllVehicleIndexes();
announceAdminAction(`JobVehiclesRespawned`);
}
@@ -1409,6 +1420,8 @@ function respawnClanVehiclesCommand(command, params, client) {
}
}
setAllVehicleIndexes();
announceAdminAction(`ClanVehiclesRespawned`);
}
@@ -1421,6 +1434,8 @@ function respawnPlayerVehiclesCommand(command, params, client) {
}
}
setAllVehicleIndexes();
announceAdminAction(`PlayerVehiclesRespawned`);
}
@@ -1433,6 +1448,8 @@ function respawnPublicVehiclesCommand(command, params, client) {
}
}
setAllVehicleIndexes();
announceAdminAction(`PublicVehiclesRespawned`);
}
@@ -1445,6 +1462,8 @@ function respawnBusinessVehiclesCommand(command, params, client) {
}
}
setAllVehicleIndexes();
announceAdminAction(`BusinessVehiclesRespawned`);
}
@@ -1464,23 +1483,21 @@ function stopRentingVehicle(client) {
// ===========================================================================
function respawnVehicle(vehicle) {
let vehicles = getServerData().vehicles;
for (let i in vehicles) {
if (vehicle == vehicles[i].vehicle) {
if (vehicles[i].spawnLocked == true) {
vehicles[i].engine = false;
for (let i in getServerData().vehicles) {
if (vehicle == getServerData().vehicles[i].vehicle) {
if (getServerData().vehicles[i].spawnLocked == true) {
getServerData().vehicles[i].engine = false;
}
if (vehicles[i].ownerType == V_VEHOWNER_JOB) {
vehicles[i].locked = true;
if (getServerData().vehicles[i].ownerType == V_VEHOWNER_JOB) {
getServerData().vehicles[i].locked = true;
}
destroyElement(vehicle);
vehicles[i].vehicle = false;
getServerData().vehicles[i].vehicle = false;
let newVehicle = spawnVehicle(vehicles[i]);
vehicles[i].vehicle = newVehicle;
setEntityData(newVehicle, "v.rp.dataSlot", i, false);
let newVehicle = spawnVehicle(getServerData().vehicles[i]);
getServerData().vehicles[i].vehicle = newVehicle;
}
}
@@ -1490,7 +1507,7 @@ function respawnVehicle(vehicle) {
// ===========================================================================
function spawnVehicle(vehicleData) {
logToConsole(LOG_DEBUG, `[V.RP.Vehicle]: Spawning ${getVehicleNameFromModel(vehicleData.model)} at ${vehicleData.spawnPosition.x}, ${vehicleData.spawnPosition.y}, ${vehicleData.spawnPosition.z} with heading ${vehicleData.spawnRotation}`);
logToConsole(LOG_DEBUG, `[V.RP.Vehicle]: Spawning ${getGameConfig().vehicles[getGame()][vehicleData.model][1]} at ${vehicleData.spawnPosition.x}, ${vehicleData.spawnPosition.y}, ${vehicleData.spawnPosition.z} with heading ${vehicleData.spawnRotation}`);
let vehicle = createGameVehicle(vehicleData.model, vehicleData.spawnPosition, vehicleData.spawnRotation);
if (!vehicle) {
@@ -1590,7 +1607,7 @@ function isVehicleOwnedByJob(vehicle, jobId) {
// ===========================================================================
function createNewDealershipVehicle(modelIndex, spawnPosition, spawnRotation, price, dealershipId, interior = 0, dimension = 0) {
function createNewDealershipVehicle(modelIndex, spawnPosition, spawnRotation, price, ownerType, dealershipId, interior = 0, dimension = 0) {
let vehicle = createGameVehicle(modelIndex, spawnPosition, spawnRotation);
if (!vehicle) {
return false;
@@ -1605,19 +1622,29 @@ function createNewDealershipVehicle(modelIndex, spawnPosition, spawnRotation, pr
tempVehicleData.spawnLocked = true;
tempVehicleData.spawnPosition = spawnPosition;
tempVehicleData.spawnRotation = spawnRotation;
tempVehicleData.ownerType = V_VEHOWNER_BIZ;
tempVehicleData.ownerType = ownerType;
tempVehicleData.ownerId = dealershipId;
tempVehicleData.needsSaved = true;
tempVehicleData.interior = interior;
tempVehicleData.dimension = dimension;
tempVehicleData.whoAdded = defaultNoAccountId;
tempVehicleData.whenAdded = getCurrentUnixTimestamp();
let slot = getServerData().vehicles.push(tempVehicleData);
setEntityData(vehicle, "v.rp.dataSlot", slot - 1, false);
if (!isGameFeatureSupported("vehicleColour")) {
tempVehicleData.colour1 = 0;
tempVehicleData.colour2 = 0;
tempVehicleData.colour3 = 0;
tempVehicleData.colour4 = 0;
}
getServerData().vehicles.push(tempVehicleData);
setAllVehicleIndexes();
}
// ===========================================================================
function createTemporaryVehicle(modelIndex, position, heading, interior = 0, dimension = 0) {
function createTemporaryVehicle(modelIndex, position, heading, interior = 0, dimension = 0, whoAdded = defaultNoAccountId) {
let vehicle = createGameVehicle(modelIndex, position, heading);
setVehicleHeading(vehicle, heading);
setElementInterior(vehicle, interior);
@@ -1629,6 +1656,10 @@ function createTemporaryVehicle(modelIndex, position, heading, interior = 0, dim
tempVehicleData.databaseId = -1;
tempVehicleData.interior = interior;
tempVehicleData.dimension = dimension;
tempVehicleData.needsSaved = true;
tempVehicleData.whoAdded = whoAdded;
tempVehicleData.whenAdded = getCurrentUnixTimestamp();
if (!isGameFeatureSupported("vehicleColour")) {
tempVehicleData.colour1 = 0;
tempVehicleData.colour2 = 0;
@@ -1636,19 +1667,16 @@ function createTemporaryVehicle(modelIndex, position, heading, interior = 0, dim
tempVehicleData.colour4 = 0;
}
let slot = getServerData().vehicles.push(tempVehicleData);
setAllVehicleIndexes();
getServerData().vehicles.push(tempVehicleData);
if (areServerElementsSupported()) {
setEntityData(vehicle, "v.rp.dataSlot", slot - 1, false);
}
setAllVehicleIndexes();
return vehicle;
}
// ===========================================================================
function createPermanentVehicle(modelIndex, position, heading, interior = 0, dimension = 0) {
function createPermanentVehicle(modelIndex, position, heading, interior = 0, dimension = 0, whoAdded = defaultNoAccountId) {
let vehicle = createGameVehicle(modelIndex, position, heading);
setVehicleHeading(vehicle, heading);
setElementInterior(vehicle, interior);
@@ -1659,6 +1687,10 @@ function createPermanentVehicle(modelIndex, position, heading, interior = 0, dim
tempVehicleData.model = modelIndex;
tempVehicleData.interior = interior;
tempVehicleData.dimension = dimension;
tempVehicleData.needsSaved = true;
tempVehicleData.whoAdded = whoAdded;
tempVehicleData.whenAdded = getCurrentUnixTimestamp();
if (!isGameFeatureSupported("vehicleColour")) {
tempVehicleData.colour1 = 0;
tempVehicleData.colour2 = 0;
@@ -1666,12 +1698,9 @@ function createPermanentVehicle(modelIndex, position, heading, interior = 0, dim
tempVehicleData.colour4 = 0;
}
let slot = getServerData().vehicles.push(tempVehicleData);
setAllVehicleIndexes();
getServerData().vehicles.push(tempVehicleData);
if (areServerElementsSupported()) {
setEntityData(vehicle, "v.rp.dataSlot", slot - 1, false);
}
setAllVehicleIndexes();
return vehicle;
}
@@ -1737,7 +1766,7 @@ function checkVehiclePurchasing(client) {
getServerData().purchasingVehicleCache.splice(getServerData().purchasingVehicleCache.indexOf(client), 1);
if (getVehicleData(getPlayerData(client).buyingVehicle).ownerType == V_VEHOWNER_BIZ || getVehicleData(getPlayerData(client).buyingVehicle).ownerType == V_VEHOWNER_NONE) {
createNewDealershipVehicle(getVehicleData(getPlayerData(client).buyingVehicle).model, getVehicleData(getPlayerData(client).buyingVehicle).spawnPosition, getVehicleData(getPlayerData(client).buyingVehicle).spawnRotation, getVehicleData(getPlayerData(client).buyingVehicle).buyPrice, getVehicleData(getPlayerData(client).buyingVehicle).ownerId);
createNewDealershipVehicle(getVehicleData(getPlayerData(client).buyingVehicle).model, getVehicleData(getPlayerData(client).buyingVehicle).spawnPosition, getVehicleData(getPlayerData(client).buyingVehicle).spawnRotation, getVehicleData(getPlayerData(client).buyingVehicle).buyPrice, getVehicleData(getPlayerData(client).buyingVehicle).ownerType, getVehicleData(getPlayerData(client).buyingVehicle).ownerId);
}
takePlayerCash(client, getVehicleData(getPlayerData(client).buyingVehicle).buyPrice);
updatePlayerCash(client);
@@ -1839,13 +1868,18 @@ function getVehicleFromDatabaseId(databaseId) {
// ===========================================================================
function isVehicleUnoccupied(vehicle) {
for (let i = 0; i <= 8; i++) {
if (vehicle.getOccupant(i) != null) {
return true;
let clients = getClients();
for (let i in clients) {
if (clients[i].player != null) {
if (clients[i].player.vehicle != false) {
if (clients[i].player.vehicle == vehicle) {
return false;
}
}
}
}
return false;
return true;
}
// ===========================================================================
@@ -1868,7 +1902,7 @@ function removeAllOccupantsFromVehicle(vehicle) {
let clients = getClients();
for (let i in clients) {
if (clients[i].player != null) {
if (clients[i].player.vehicle != null) {
if (clients[i].player.vehicle != false) {
if (clients[i].player.vehicle == vehicle) {
removePlayerFromVehicle(clients[i]);
}
@@ -1920,9 +1954,13 @@ function isPlayerInVehicleDriverSeat(client) {
function despawnAllVehicles() {
for (let i in getServerData().vehicles) {
destroyGameElement(getServerData().vehicles[i].vehicle);
getServerData().vehicles[i].vehicle = null;
if (getServerData().vehicles[i].vehicle != false) {
destroyGameElement(getServerData().vehicles[i].vehicle);
getServerData().vehicles[i].vehicle = false;
}
}
setAllVehicleIndexes();
}
// ===========================================================================
@@ -1936,4 +1974,18 @@ function updateVehicleSavedPositions() {
}
}
// ===========================================================================
function getVehicleDataIndexFromVehicle(vehicle) {
if (isVehicleObject(vehicle)) {
for (let i in getServerData().vehicles) {
if (getServerData().vehicles[i].vehicle == vehicle) {
return i;
}
}
}
return -1;
}
// ===========================================================================

View File

@@ -142,4 +142,12 @@ const V_NPC_ACTION_GUARD_AREA = 7;
const V_VEHSEAT_DRIVER = 0;
const V_VEHSEAT_FRONTPASSENGER = 1;
const V_VEHSEAT_REARLEFTPASSENGER = 2;
const V_VEHSEAT_REARRIGHTPASSENGER = 3;
const V_VEHSEAT_REARRIGHTPASSENGER = 3;
// PayPhone States
const V_PAYPHONE_STATE_NONE = 0;
const V_PAYPHONE_STATE_IDLE = 1;
const V_PAYPHONE_STATE_RINGING = 2;
const V_PAYPHONE_STATE_ACTIVE_CALL = 3;
const V_PAYPHONE_STATE_BROKEN = 4;
const V_PAYPHONE_STATE_CALLING = 5;

File diff suppressed because it is too large Load Diff

44
scripts/shared/queue.js Normal file
View File

@@ -0,0 +1,44 @@
// ===========================================================================
// Vortrex's Roleplay Resource
// https://github.com/VortrexFTW/v-roleplay
// ===========================================================================
// FILE: queue.js
// DESC: Provides simple queue functions
// TYPE: Shared (JavaScript)
// ===========================================================================
class QueueData {
constructor(func, duration) {
this.duration = duration;
this.func = func;
this.nextUp = null;
if (this.nextUp != null) {
if (duration <= 0) {
this.nextUp.func();
} else {
delayedFunction(this.nextUp.func, this.duration);
}
}
}
next(func, duration) {
this.nextUp = createQueue(func, duration);
}
}
// ===========================================================================
function createQueue(func, duration) {
return new QueueData(func, duration);
}
// ===========================================================================
function delayedFunction(func, duration) {
setTimeout(function () {
func();
}, duration);
}
// ===========================================================================

View File

@@ -7,6 +7,14 @@
// TYPE: Shared (JavaScript)
// ===========================================================================
let dayHourStart = 6;
let dayMinuteStart = 0;
let dayMinuteWarningStart = 5;
let nightHourStart = 18;
let nightMinuteStart = 0;
let nightMinuteWarningStart = 5;
let emojiNumbers = ["➊", "➋", "➌", "➍", "➎", "➏", "➐", "➑", "➒"];
//let emojiNumbers = ["①", "②", "③", "④", "⑤", "⑥", "⑦", "⑧", "⑨"];
//let emojiNumbers = ["1⃣", "2⃣", "3⃣", "4⃣", "5⃣", "6⃣", "7⃣", "8⃣", "9⃣"];
@@ -1370,11 +1378,24 @@ let placesOfOrigin = [
"Blaine County",
"Red County",
"Bone County",
"Lost Heaven",
"Empire Bay",
"Other",
];
// ===========================================================================
let payPhoneStateNames = [
"None/Unknown",
"Idle",
"Ringing",
"Active Call",
"Broken",
"Calling"
];
// ===========================================================================
function getGameConfig() {
return gameData;
}
@@ -2303,25 +2324,31 @@ function removeHexColoursFromString(str) {
// ===========================================================================
function removeSlashesFromString(str) {
let matchRegex = /\//gi;
str.replace(matchRegex, ``);
if (str == null) {
return false;
}
if (str == "") {
let matchRegex = /\//gi;
str.replace(matchRegex, ``);
}
return str;
}
// ===========================================================================
async function waitUntil(condition) {
return new Promise((resolve) => {
let interval = setInterval(() => {
if (!condition()) {
return;
}
clearInterval(interval);
resolve();
}, 1);
});
function waitUntil(condition) {
//return new Promise((resolve) => {
// let interval = setInterval(() => {
// if (!condition()) {
// return;
// }
//
// clearInterval(interval);
// resolve();
// }, 1);
//});
}
// ===========================================================================
@@ -3208,7 +3235,7 @@ function fillLeadingZeros(number, length) {
// ===========================================================================
function isMainWorldScene(sceneName) {
return (sceneName == "v.rp.mainWorldScene");
return (sceneName == "V.RP.MAINWORLD" || sceneName == "");
}
// ===========================================================================
@@ -3225,11 +3252,11 @@ function isNightTime(hour) {
function isServerGoingToChangeMapsSoon(hour, minute) {
if (server.mapName == "FREERIDENOC") {
if (hour == 6 && minute >= 30) {
return true
if (hour == dayHourStart && minute < (dayMinuteStart - dayMinuteWarningStart)) {
return true;
}
} else if (server.mapName == "FREERIDE") {
if (hour == 18 && minute >= 30) {
if (hour == dayHourStart && minute < (nightMinuteStart - nightMinuteWarningStart)) {
return true;
}
}
@@ -3253,4 +3280,10 @@ function getWeatherData(weatherIndex, gameId = getGame()) {
return getGameConfig().weather[gameId][weatherIndex];
}
// ===========================================================================
function getPayPhoneStateName(state) {
return payPhoneStateNames[state];
}
// ===========================================================================

View File

@@ -248,7 +248,7 @@ mexui.isAnyWindowShown = function () {
mexui.setInput = function (showInput) {
gui.showCursor(showInput, !showInput);
if (localClient.player && game.game >= GAME_GTA_IV) {
if (localClient.player && game.game <= GAME_GTA_IV) {
if (showInput)
game.setCameraLookAtEntity(new Vec3(game.cameraMatrix.m41, game.cameraMatrix.m42, game.cameraMatrix.m43), localPlayer, false);
else