diff --git a/.gitignore b/.gitignore
index b95e158d..374f80f7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
.vs/
-.git/
\ No newline at end of file
+.git/
+config/*
\ No newline at end of file
diff --git a/IDEAS.md b/IDEAS.md
index 1e0de21e..09465c54 100644
--- a/IDEAS.md
+++ b/IDEAS.md
@@ -1,12 +1,12 @@
-Ideas for Asshat Gaming RP!
+# Ideas
+## For Asshat Gaming RP
==============================================================================================================
-NOTICE: Most of these ideas are totally random and some might be unrealistic. Every time I thought of something, I just immediately threw it into this file. I never checked to see if I had already added it, so there may be duplicates or similar entries spread out and unorganized.
+**NOTICE: Most of these ideas are totally random and some might be unrealistic. Every time I thought of something, I just immediately threw it into this file. I never checked to see if I had already added it, so there may be duplicates or similar entries spread out and unorganized.**
-==============================================================================================================
-
-* Businesses (some from GTA Online)
+---
+### Businesses (some from GTA Online)
* Nightclubs
* Executive Offices
* Warehouses
@@ -14,94 +14,95 @@ NOTICE: Most of these ideas are totally random and some might be unrealistic. Ev
* Houses
* Garages
* Casinos
-
-* Interactive peds with each one having a background story, characteristics, certain people or groups they like/dislike.
+---
+### Interactive peds with each one having a background story, characteristics, certain people or groups they like/dislike.
* Procedurally generated?
-
+---
* Nightclubs, bars, etc can employ "bouncer" peds that either prevent entry to certain people, or kick people out.
-
-* Background ambience.
+---
+### Background ambience.
* Anonymous city traffic and pedestrians
* They come and go and aren't persistent.
* Police peds/traffic will pursue if player has 1+ stars and comes within range and line of sight.
-
-* Named NPCs
+---
+### Named NPCs
* Persistent
* Move from place to place. Eat at restaurants, drive home, to work, get drunk at a bar, etc.
* Different personalities
* Relationship levels with each player and clan. If you piss them off, they won't do business with you.
-
-* Firefighter Job
+---
+### Firefighter Job
* Vehicles catch on fire instead of blowing up.
* Random property fires can occur.
* Firetrucks can "spray" a fire, lowering the damage until it is extinguished (Aim detection).
-
-* Streetsweeper Job
+---
+### Streetsweeper Job
* Instead of checkpoints, show actual messes on the road.
* Drive over the messes with the right vehicle to "clean" the mess.
* Only show messes if at least one player is on duty.
-
-* Garbageman Job
+---
+### Garbageman Job
* Instead of checkpoints, have trashbag objects outside of properties or wherever.
* Allow the trashtruck drivers to "pickup" the trashbag, then "place" into the truck.
* If the truck is full, deliver the trashbags to the dump.
* Only show trashbags if at least one player is currently doing the job.
-
-* Mailman Job
+---
+### Mailman Job
* Use a white solid van (Pony maybe) as a mail van.
* Load mail at the post office, and drive a specific route to "deliver" mail.
* Return the truck for payment.
-
-* Vehicle Towing
+---
+### Vehicle Towing
* Use a Yankee or something to store the vehicle "inside" (just make the car disappear) until better sync options are built.
* Universal command to tow/release a vehicle ( /tow ).
* Attach to nearest vehicle.
-
-* Item System
+---
+### Item System
* Several item types, including armour, skins, weapons, drugs, materials, and more.
* Items can be dropped and picked up.
* Items can be stored in a vehicle trunk or dash compartment.
* Items can be given, taken, or used.
-
-* Payphones
+---
+### Payphones
* Make built in payphones usable (detect position, ring sound, etc)
* Payphones can be called, making them ring to nearby players.
-
-* Multiple bed hospital.
+---
+### Multiple bed hospital.
* When one is taken, use the next one.
* If all are full, have a waiting list.
* Allow people to go in and lay on a bed to heal (or use a check-in system)
-
-* Several NPC's
+---
+### Several NPC's
* Paramedics/Doctors at hospitals,
* LC/VC/LS/SF/LV police dept desk clerk and dispatcher.
* Jail guard
* Interactive. Go up and talk to them for responses etc
-
-* Use permissions/flag system for everything.
+---
+### Use permissions/flag system for everything.
* Admin abilities
* Moderation (muted/frozen/etc)
* LEO abilities
* Clan abilities
* Account Settings
* etc
-
-* Interiors
+---
+### Interiors
* For games with interiors, properties inside of properties (possibly make it a sub-property, but using a "type" to define it. May not be necessary) AKA a business inside a business (illegal back room gambling, anyone?)
-
-* Stealable skins. When one is stolen, it is replaced by the thief's skin
-
-* Black market for anything.
+---
+### Stealable skins.
+ * When one is stolen, it is replaced by the thief's skin
+---
+### Black market for anything.
* Smuggled drugs
* LEO items
* Weapons and weapon upgrades
* Illegal vehicle upgrades like NOS.
-
-* Drug houses and weed farms.
+---
+### Drug houses and weed farms.
* Make weed only plantable in certain areas.
* Drug houses aren't limited to the type of house, as anybody can deal or use in any place.
-
-* Size-based inventories.
+---
+### Size-based inventories.
* Items should have a size and inventories can only hold so much.
* Items inside of items. This could be (but not limited to):
* Briefcases
@@ -110,15 +111,15 @@ NOTICE: Most of these ideas are totally random and some might be unrealistic. Ev
* Trashbags
* Boxes/crates
* Use the item sizes for storage capacity
-
-* Weapons like DayZ.
+---
+### Weapons like DayZ.
* Multiple weapon types that issue different damages.
* Ammo clips that only fit a compatible weapon
* Different clip types hold different amounts of ammo in them (and specific ammo types)
* Hollow point and armor piercing round types
* Modifications. Flashlight, silencer, bigger clip, tracer, scope, etc.
-
-* Crime scene investigations.
+---
+### Crime scene investigations.
* Blood
* Fingerprints
* Ballistics/bullets on ground, in objects, walls, etc.
@@ -129,8 +130,8 @@ NOTICE: Most of these ideas are totally random and some might be unrealistic. Ev
* Can be cleaned up by anybody (including the murderer or suspects)
* Showering or swimming clears blood from body
* Rain washes away blood outside (if not under an object or bridge). Perhaps line of sight check with high up Z at same coord?
-
-* Huge police interiors and garages.
+---
+### Police interiors and garages.
* Multiple interrogation rooms with blocked sound (chat is localized to that room)
* Multiple offices for ranking members
* Detective squad rooms with a CO office
@@ -138,15 +139,15 @@ NOTICE: Most of these ideas are totally random and some might be unrealistic. Ev
* Crime scene lab
* Cell block area (or multiple cell blocks)
* Elevators that can take you to multiple levels of the building (and roof/garage).
-
-* Custom MDC.
+---
+### Police Computer
* Arrest logs
* Past tickets
* Officer reports
* Investigation info
* APB list
-
-* Admin panel.
+---
+### Admin panel.
* Reports
* Multiple actions for each
* Viewing info and past reports/actions on the reporter and the situation.
@@ -155,45 +156,54 @@ NOTICE: Most of these ideas are totally random and some might be unrealistic. Ev
* Action
* Weapon/Kill/Death
* Others
-
-* Log everything possible.
-
-* Depending on type of injuries, have multiple results occur over time.
+---
+### Logging
+ * Log everything possible
+---
+### Injuries
+ * Depending on type of injuries, have multiple results occur over time.
* Gunshots lead to bleeding which could lead to passing out for loss of blood.
* Post-treatment effects are also possible including siezures from blunt force trauma.
-
-* Custom actions to have different results. Interactive-ness.
+---
+### Interactive Actions
* Hotwiring a car could be successful or could also fail, depending on vehicle type and variance.
* The user has to go through each step in order to complete the task.
* Hotwiring could have things like splitting and joining wires to make the car start or the alarm stop.
* Include medical procedures in this idea. Surgeries, gunshot wounds, etc
* Require certain tools to perform different actions.
* Different vehicles have different wires to use to be successful.
-
-* Limit weapons per person.
+---
+### Limit weapons per person.
* Have a visible large weapon if they have one (attached)
* Concealable smaller weapon.
-
-* Officers usually have a utility belt. Allow it to hold equipment as well.
-
-* Trunks can hold players/peds (not visibly) and items and is size based.
-
-* Get "inside" the back of trucks/trailers and store items inside.
+ * Officers usually have a utility belt. Allow it to hold equipment as well.
+---
+###
+---
+### Vehicle Trunks
+ * Can hold tied up players/peds
+ * Can hold items
+ * Size/capacity depending on vehicle
+---
+### Vehicle Interiors
+ * Get "inside" the back of trucks/trailers and store items inside.
* Use an interior for this and allow dropped items (including crates and boxes and etc).
* Shouts and certain speech can be heard outside wherever the truck is at.
* Vehicle sink or explode while inside the back causes death and objects destroyed.
* Also for airplane interiors
-
-* Multi space impound lot. When retrieving a car from impound, spawn it in the first empty space that isn't obstructed.
-
-* Weapons obtain damage from use and time. If not cared for, they can have decreased damage from shots, or even break or malfunction
+---
+### Impound Lot
+ * Multi space impound lot. When retrieving a car from impound, spawn it in the first empty space that isn't obstructed.
+---
+### Weapon Wear and Tear
+ * Weapons obtain damage from use and time. If not cared for, they can have decreased damage from shots, or even break or malfunction
* Cleaning weapons improves reliability
-
-* Weapons have identifying parts like barrel bores (for ballistics) and serial numbers. Serial numbers can be removed.
-
-* GUI color schemes (https://vortrex.info/f/1/4eca24d1.png) with a settings page to switch them. Orange, red, blue, purple, etc.
-
-* Police
+---
+### Weapon Identification
+ * Weapons have identifying parts like barrel bores (for ballistics) and serial numbers.
+ * Serial numbers can be removed.
+---
+### Police Behavior
* Stars
* 1 star for an initial misdemeanor. Traffic violation, pedestrian crime, etc. Police will pursue to fine/ticket.
* 2 stars for any subsequent crimes committed in police presence, after receiving one star and no action taken (if you don't pull over, run on foot, etc). Results in arrest.
@@ -203,8 +213,11 @@ NOTICE: Most of these ideas are totally random and some might be unrealistic. Ev
* NPC police will chase you if you have 1+ stars. If you lose them with 2 or less stars, they go away unless you are sighted by another officer before cooldown.
* Any traffic violation that takes place within LOS and range of police will cause them to chase you until you pull over.
* Failure to pull over within a timely manner, or breaking another law before pulling over adds a second star. They won't fine you at this level, only arrest or worse.
-
-* NPC Ideas
+ ```
+ Player police officers can issue an APB for a player suspect. NPC police drive and walk around as normal in the game but if they spot the player suspect within a certain distance and line of sight, their position is sent to any player police officers via radio and shown as a blip on the radar. If the suspect evades the NPC police, the blip fades out at the last seen suspect location and eventually disappears, no longer available to player police officers. This means that the blip will continue to show other officers at the suspect's updated location until a) all police officers lose line of sight, b) suspect gets too far away or c) enters a house/business (losing line of sight with police unless they enter). All of these will cause the blip to show the suspects last known and seen location while the blip fades out and eventually disappears. Any officer that re-establishes line of sight within a certain distance will cause the suspect's blip to show again for all police. NPC police will NOT use the built-in wanted level system because this causes excessive spawning of police no matter where the suspect is generally completely unfair. Instead, scripting functions like ped.runTo, vehicle.setCarMission, vehicle.setCruiseSpeed, etc will be used to pursue the suspect. The logic in these functions is not perfect. The NPC officer can wreck the police car, get slowed down by traffic or stuck on something altogether, and the ped can be evaded by continously going around corners and such. All of this provides the ability for the suspect to have a chance of getting away. Changing skin/clothes or driving different/unknown vehicles reduces the NPC's line of sight and distance checking and thus reduces their chance of identifying them when near
+ ```
+---
+### NPC Types
* Bodyguards
* Biker gang formation
* Convoy Line
@@ -220,46 +233,39 @@ NOTICE: Most of these ideas are totally random and some might be unrealistic. Ev
* Mechanic
* Tweakers
* Bouncers
-
-* Accents
+---
+### Accents
* Shown before message ... "[Japanese] John Smith says: hello"
* Pre-set accent choices
* Custom accent
-
-* Speakerphone
+---
+### Speakerphone
* While on a phone call, using /speakerphone or something can allow others near the person on the phone to hear and be heard over the call.
-
-
-* Player police officers can issue an APB for a player suspect. NPC police drive and walk around as normal in the game but if they spot the player suspect within a certain distance and line of sight, their position is sent to any player police officers via radio and shown as a blip on the radar. If the suspect evades the NPC police, the blip fades out at the last seen suspect location and eventually disappears, no longer available to player police officers. This means that the blip will continue to show other officers at the suspect's updated location until a) all police officers lose line of sight, b) suspect gets too far away or c) enters a house/business (losing line of sight with police unless they enter). All of these will cause the blip to show the suspects last known and seen location while the blip fades out and eventually disappears. Any officer that re-establishes line of sight within a certain distance will cause the suspect's blip to show again for all police. NPC police will NOT use the built-in wanted level system because this causes excessive spawning of police no matter where the suspect is generally completely unfair. Instead, scripting functions like ped.runTo, vehicle.setCarMission, vehicle.setCruiseSpeed, etc will be used to pursue the suspect. The logic in these functions is not perfect. The NPC officer can wreck the police car, get slowed down by traffic or stuck on something altogether, and the ped can be evaded by continously going around corners and such. All of this provides the ability for the suspect to have a chance of getting away. Changing skin/clothes or driving different/unknown vehicles reduces the NPC's line of sight and distance checking and thus reduces their chance of identifying them when near.
-
-* Casinos
-
-* Pebble companion app
-
-* More GUI
- * Basic layouts
- * List
- * Columned List (Grid?)
- * Single Text Input Prompt
- * Complex Layouts
- * Info boxes for any type of server entity
- * Admin functions for each one (ban, kick, delete, set owner, etc)
- * Chat log
- * Lists of submitted ideas and bug reports
-
-* Web API
- * REST-like URLs
- * Type shortened to database table prefix style (/acct, /veh, etc)
-
-* Companion app for my Pebble watch (Rebble)
+---
+### Casinos
+ * Will have to be custom-made and server sided
+ * Using server side will also allow casino gameplay in games where they don't exist
+---
+### Companion app
+ * Android/iOS
+ * Pebble watch (Uses phone companion app for connection)
* Whole thing streamlined
* Server select, then use GUI colours of server
* Connected players
* Links to account/character info
- * Character Info leads to owned vehicles, houses, businesses, current clan, etc
+ * Character info leads to owned vehicles, houses, businesses, current clan, etc
* Clan info leads to owned businesses, houses, vehicles, etc
* Business, house, vehicle info has links back to owners info pages
- * Alerts for reports, submitted bugs/ideas, hacker detection
+ * Notifications
+ * (Vehicle) For vehs with upgraded alarms, show when bumped or broken into
+ * (Business) For upgraded alarms, show when broken into
+ * (House) For upgraded alarms, show when broken into
+ * (Clan) House/Business/Vehicle bought/sold
+ * (Clan) Member joined/left
+ * (Clan) Point and turf war start/finish, add results
+ * (Admin) Reports
+ * (Admin) Hacker detection
+ * (Dev) Submitted bugs/ideas
* Silent mode to block incoming alerts
* Moderation action choices.
* Players
@@ -276,5 +282,69 @@ NOTICE: Most of these ideas are totally random and some might be unrealistic. Ev
* Config options
* Shutdown, restart, gmx, etc
* Alert (probably pre-made messages, configurable in pebble app)
-
-- Newspaper GUI
\ No newline at end of file
+---
+### More GUI
+ * Basic layouts
+ * List
+ * Columned List (Grid?)
+ * Single Text Input Prompt
+ * Complex Layouts
+ * Info boxes for any type of server entity
+ * Admin functions for each one (ban, kick, delete, set owner, etc)
+ * Chat log
+ * Lists of submitted ideas and bug reports
+---
+### Web API
+ * REST-like URLs
+ * Type shortened to database table prefix style (/acct, /veh, etc)
+ * Auth token header
+---
+### Newspaper GUI
+---
+### Tutorial Stuff
+ * Two sets of flags for each tutorial. One for "already finished" and "declined tutorial"
+ * Tutorials will be in their own dimension (tutorial dimension start + client index)
+ * Tutorials
+ * Business (Ask to take tutorial when purchasing one)
+ * House (Ask to take tutorial when purchasing/renting one)
+ * Job (One for each job. Ask to take tutorial when taking a job)
+ * Spawn job vehicle and put arrow on it to indicate as a job vehicle
+ * For route jobs, point camera at random route stop and show vehicle driving to it
+ * Show basic usage of each job's features through steps (i.e. for police: tazing, cuffing, detaining, arresting a player)
+ * Vehicle (ask to take tutorial when purchasing one. Show item in trunk/dash too)
+ * Set camera to look at DMV for registering vehicle
+ * Set camera to random pay and spray to modify/repair/recolour vehicle
+ * Clan (Ask to take tutorial when being set as owner of clan)
+ * Show rank management
+ * Show member management
+ * Show vehicle management
+ * Show business/house management
+ * Show turf wars
+ * Show point wars
+---
+### Inventory Display
+ * Player choice
+ * Minecraft-style hotbar
+ * GTA V style radial wheel
+---
+### Usable world furniture
+ * Key press to use
+ * ATMs
+ * Chairs, benches, beds, restaurant seats, etc
+ * Specific transition anims where possible, otherwise warp to locked anim (i.e. instant stand to sit)
+ * Available offsets
+---
+### Pointing
+ * Key to point sort of like FiveM has.
+ * Use a 3D primitive on the spot thats pointed to, if no anim available.
+---
+### Multi-command one-liners
+Obviously this would still be using slashes for commands still.
+The way this works is simple: Every command returns a value `{RETURN}`, and provides indexed numerical references to it's args that can be *piped* to another command `{1}`, `{2}`, etc
+For example, the /tempveh command adds a vehicle and provides both a reference to the vehicle itself (`{RETURN}`) and a reference to it's only argument (`{1}`).
+Some commands already implement a final, optional command to override the default chosen entity to act on (for example, `/bizname Some Business 3` will set business ID 3's name instead of the closest business to the player. Only works for staff with the manageBusinesses permission or if the player using it owns or is in the clan that owns business ID 3 and has the ability to set it's name.
+So this: `/tempveh infernus | /vehrgb 0 0 0 0 {RETURN} | /vehrgb 1 {2} {3} {4} {RETURN}` Would spawn a temporary infernus and immediately set both colours as completely black RGB values.
+---
+### Real time display
+Steam has the player's local time on it's overlay. Something like that. Toggleable in account settings of course.
+---
\ No newline at end of file
diff --git a/README.md b/README.md
index a26f9772..a4f1fd43 100644
--- a/README.md
+++ b/README.md
@@ -9,22 +9,6 @@ This is the roleplay resource for Asshat Gaming's GTAC servers
* testing - The next upcoming release. All feature/fix/change branches are merged into this one
* feature/fix/change - This is where the stuff you're currently working on goes into.
-### Getting Started
-* Download the GTAC server to your local PC. This will be your local test server.
-* Unzip the server, and edit the server config (default is server.xml) to your liking.
-* Add a CVAR to the server config called `devserver` and set it's value to "1" to use the dev server database.
-* Run plink.exe to create an SSH tunnel.
- * `plink.exe gtacrp.asshatgaming.com -P 40393 -l USERNAME -i PATHTOKEY -L 127.0.0.1:3307:127.0.0.1:3306`
- * Replace USERNAME with your username
- * Replace PATHTOKEY with the full file path to your private key
- * Put the edited command into a batch file (.bat) to make it easier to use next time.
-* Add a CVAR to the server config called `databaseport` and set it's value to 3307.
-* Clone this git repository into a subdirectory within the server's resources folder.
-* Add the subdirectory's folder name to the resources section of the server config.
-* Start the server to make sure it works and connects.
-* Make a branch based on `testing` for every new feature/fix/change and prefix it with one of those (i.e. `feature-something`)
-* Test the feature, and if it works, merge the branch for it into testing branch
-
### Scripting Style
* Always use camelCase, even for event names.
* Use a util function where possible. Keep raw logic in command/event/network handlers to a minimum.
diff --git a/TODO.md b/TODO.md
index 7181c021..2b2a7625 100644
--- a/TODO.md
+++ b/TODO.md
@@ -1,19 +1,16 @@
* Ice cream job
* VC: -862.39, -578.35, 11.10
-
+------------------------------------------------------
+* Change structure of item types to include only **one** set of items
+ * Use a new table for game-specific data (model, obj pos/rot/scale, etc)
+------------------------------------------------------
* Cut down on engine/lights/lock messages.
* Account settings to toggle tips
* Get coords for more bus routes.
-
* Add more jobs
-
------------------------------------------------------
For grand opening:
- Get remaining interiors set up for the businesses/houses in Vice City
-- Add command help option. Pick sub option:
- - Put as optional arg in command handler func like the LU script
- - Or put in commandData class (probably this one)
-- Add police officer commands logic
- Tutorial
- Pick up item (grab bottle of beer off ground)
- Equip item (switch to bottle of beer item)
@@ -24,3 +21,16 @@ For grand opening:
- Take second beer from crate
- Store second beer in trunk
------------------------------------------------------
+* Look into using TLS instead of SSL for SMTP email usage.
+------------------------------------------------------
+* Item management commands
+ * Item Types
+ * Create
+ * Set base price
+ * Set model
+ * Set drop position offset
+ * Set drop rotation offset
+------------------------------------------------------
+
+------------------------------------------------------
+* Change pizza delivery job to pick a random house door instead of pre-established places on the street.
\ No newline at end of file
diff --git a/asshat-rp.code-workspace b/asshat-rp.code-workspace
new file mode 100644
index 00000000..876a1499
--- /dev/null
+++ b/asshat-rp.code-workspace
@@ -0,0 +1,8 @@
+{
+ "folders": [
+ {
+ "path": "."
+ }
+ ],
+ "settings": {}
+}
\ No newline at end of file
diff --git a/config/database.json b/config/database.json
new file mode 100644
index 00000000..bee556f7
--- /dev/null
+++ b/config/database.json
@@ -0,0 +1,8 @@
+{
+ "host": "",
+ "user": "",
+ "pass": "",
+ "name": "",
+ "port": 3306,
+ "usePersistentConnection": true
+}
\ No newline at end of file
diff --git a/config/email.json b/config/email.json
new file mode 100644
index 00000000..c1e09ffe
--- /dev/null
+++ b/config/email.json
@@ -0,0 +1,19 @@
+{
+ "smtp": {
+ "host":"",
+ "port":"",
+ "username":"",
+ "password":"",
+ "from":"",
+ "fromName":"",
+ "useTLS":"true"
+ },
+ "bodyContent": {
+ "confirmEmail": "Welcome to Asshat Gaming Roleplay for GTA Connected!\nPlease confirm your email by using the command /verifyemail in-game.\n\nYour verification code is: {VERIFICATIONCODE}",
+ "emailConfirmed": "Your email has been confirmed on Asshat Gaming Roleplay for GTA Connected!\nYou may now use this email to reset your password, require two-factor authentication on login, receive offline notifications, and more!",
+ "twoFactorAuthentication": "Please enter the following code to continue on Asshat Gaming's roleplay server for {GAMENAME}: {2FACODE}",
+ "accountAuthSuccessAlert": "You or someone else has successfully logged in to your account on the Asshat Gaming roleplay server for {GAMENAME}.\nIP Address: {IPADDRESS}\nLocation: {LOCATION}\nTimestamp: {TIMESTAMP}",
+ "accountAuthFailAlert": "You or someone else has failed to login to your account on the Asshat Gaming roleplay server for {GAMENAME}.\nIP Address: {IPADDRESS}\nLocation: {LOCATION}\nTimestamp: {TIMESTAMP}",
+ "offlineMessageAlert": "You have received a private message on the Asshat Gaming roleplay server for {GAMENAME}. You are receiving this notification because you enabled message notifications via email when you're not connected to the server.\nFrom: {FROMNAME}\nTimestamp: {TIMESTAMP}\nMessage: {MESSAGE}"
+ }
+}
\ No newline at end of file
diff --git a/config/keybind.json b/config/keybind.json
new file mode 100644
index 00000000..3e815a85
--- /dev/null
+++ b/config/keybind.json
@@ -0,0 +1,119 @@
+{
+ "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": "f",
+ "commandString": "passenger",
+ "keyState": 3
+ },
+ {
+ "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": "i 0",
+ "keyState": 1
+ },
+ {
+ "keyName": "1",
+ "commandString": "i 1",
+ "keyState": 1
+ },
+ {
+ "keyName": "2",
+ "commandString": "i 2",
+ "keyState": 1
+ },
+ {
+ "keyName": "3",
+ "commandString": "i 3",
+ "keyState": 1
+ },
+ {
+ "keyName": "4",
+ "commandString": "i 4",
+ "keyState": 1
+ },
+ {
+ "keyName": "5",
+ "commandString": "i 5",
+ "keyState": 1
+ },
+ {
+ "keyName": "6",
+ "commandString": "i 6",
+ "keyState": 1
+ },
+ {
+ "keyName": "7",
+ "commandString": "i 7",
+ "keyState": 1
+ },
+ {
+ "keyName": "8",
+ "commandString": "i 8",
+ "keyState": 1
+ },
+ {
+ "keyName": "9",
+ "commandString": "i 9",
+ "keyState": 1
+ },
+ {
+ "keyName": "e",
+ "commandString": "action primary",
+ "keyState": 3
+ }
+ ]
+}
\ No newline at end of file
diff --git a/config/roleplay.json b/config/roleplay.json
new file mode 100644
index 00000000..82e0ed96
--- /dev/null
+++ b/config/roleplay.json
@@ -0,0 +1,27 @@
+{
+ "accents": [
+ "English",
+ "French",
+ "Russian",
+ "Scottish",
+ "Irish",
+ "Spanish",
+ "Southern American",
+ "Italian",
+ "Australian",
+ "Jamaican",
+ "Israeli",
+ "Dutch",
+ "Brazilian",
+ "Portuguese",
+ "German",
+ "Canadian",
+ "Chinese",
+ "Japanese",
+ "Turkish",
+ "Korean",
+ "Estonian",
+ "Sicilian",
+ "Indian"
+ ]
+}
\ No newline at end of file
diff --git a/meta.xml b/meta.xml
index 14889b51..cebbc90b 100644
--- a/meta.xml
+++ b/meta.xml
@@ -4,14 +4,11 @@
-
-
-
@@ -26,7 +23,10 @@
+
+
+
@@ -37,17 +37,20 @@
+
+
+
-
+
@@ -74,14 +77,17 @@
+
+
+
-
-
-
+
+
+
@@ -90,125 +96,19 @@
-
+
+
+
+
+
+
+
+
+
-
-
+
+
+
@@ -273,4 +173,4 @@
-
\ No newline at end of file
+
diff --git a/scripts/client/afk.js b/scripts/client/afk.js
index 81e3d00d..3619aaf5 100644
--- a/scripts/client/afk.js
+++ b/scripts/client/afk.js
@@ -1,35 +1,40 @@
// ===========================================================================
// Asshat-Gaming Roleplay
// https://github.com/VortrexFTW/gtac_asshat_rp
-// Copyright (c) 2020 Asshat-Gaming (https://asshatgaming.com)
-// ---------------------------------------------------------------------------
+// Copyright (c) 2021 Asshat-Gaming (https://asshatgaming.com)
+// ===========================================================================
// FILE: afk.js
// DESC: Provides AFK detection
// TYPE: Client (JavaScript)
// ===========================================================================
-// -------------------------------------------------------------------------
+function initAFKScript() {
+ logToConsole(LOG_DEBUG, "[Asshat.AFK]: Initializing AFK script ...");
+ logToConsole(LOG_DEBUG, "[Asshat.AFK]: AFK script initialized!");
+}
-addEventHandler("OnLostFocus", function(event) {
- triggerNetworkEvent("ag.afk", true);
- if(localPlayer != null) {
- localPlayer.collisionsEnabled = false;
- gta.setCiviliansEnabled(false);
- gta.setTrafficEnabled(false);
- }
-});
+// ===========================================================================
-// -------------------------------------------------------------------------
+function processLostFocusAFK(event) {
+ sendServerNewAFKStatus(true);
+ //if(localPlayer != null) {
+ // localPlayer.collisionsEnabled = false;
+ // gta.setCiviliansEnabled(false);
+ // gta.setTrafficEnabled(false);
+ //}
+}
-addEventHandler("OnFocus", function(event) {
- triggerNetworkEvent("ag.afk", false);
- if(localPlayer != null) {
- localPlayer.collisionsEnabled = true;
- if(gta.game != GAME_GTA_SA) {
- gta.setCiviliansEnabled(true);
- }
- gta.setTrafficEnabled(true);
- }
-});
+// ===========================================================================
-// -------------------------------------------------------------------------
\ No newline at end of file
+function processFocusAFK(event) {
+ sendServerNewAFKStatus(false);
+ //if(localPlayer != null) {
+ // localPlayer.collisionsEnabled = true;
+ // if(gta.game != GAME_GTA_SA) {
+ // gta.setCiviliansEnabled(true);
+ // }
+ // gta.setTrafficEnabled(true);
+ //}
+}
+
+// ===========================================================================
\ No newline at end of file
diff --git a/scripts/client/chatbox.js b/scripts/client/chatbox.js
index 44e75bc4..8e84e448 100644
--- a/scripts/client/chatbox.js
+++ b/scripts/client/chatbox.js
@@ -1,39 +1,65 @@
// ===========================================================================
// Asshat-Gaming Roleplay
// https://github.com/VortrexFTW/gtac_asshat_rp
-// Copyright (c) 2020 Asshat-Gaming (https://asshatgaming.com)
-// ---------------------------------------------------------------------------
+// Copyright (c) 2021 Asshat-Gaming (https://asshatgaming.com)
+// ===========================================================================
// FILE: chatbox.js
// DESC: Provides extra chatbox features
// TYPE: Client (JavaScript)
// ===========================================================================
-// ---------------------------------------------------------------------------
+// ===========================================================================
let chatBoxHistory = [];
let bottomMessageIndex = 0;
+let maxChatBoxHistory = 500;
let scrollAmount = 1;
let maxChatBoxLines = 6;
-bindKey(SDLK_PAGEUP, KEYSTATE_DOWN, chatBoxScrollUp);
-bindKey(SDLK_PAGEDOWN, KEYSTATE_DOWN, chatBoxScrollDown);
+// ===========================================================================
-// ---------------------------------------------------------------------------
+function initChatBoxScript() {
+ logToConsole(LOG_DEBUG, "[Asshat.ChatBox]: Initializing chatbox script ...");
+ bindChatBoxKeys();
+ logToConsole(LOG_DEBUG, "[Asshat.ChatBox]: Chatbox script initialized!");
+}
-addNetworkHandler("ag.m", function(messageString, colour) {
+// ===========================================================================
+
+function bindChatBoxKeys() {
+ bindKey(SDLK_PAGEUP, KEYSTATE_DOWN, chatBoxScrollUp);
+ bindKey(SDLK_PAGEDOWN, KEYSTATE_DOWN, chatBoxScrollDown);
+}
+
+// ===========================================================================
+
+function unBindChatBoxKeys() {
+ unbindKey(SDLK_PAGEUP);
+ unbindKey(SDLK_PAGEDOWN);
+}
+
+// ===========================================================================
+
+function receiveChatBoxMessageFromServer(messageString, colour) {
message(messageString, colour);
addToChatBoxHistory(messageString, colour);
bottomMessageIndex = chatBoxHistory.length-1;
-});
+}
-// ---------------------------------------------------------------------------
+// ===========================================================================
+
+function setChatScrollLines(amount) {
+ scrollAmount = amount;
+}
+
+// ===========================================================================
function addToChatBoxHistory(messageString, colour) {
chatBoxHistory.push([messageString, colour]);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function chatBoxScrollUp() {
if(bottomMessageIndex > maxChatBoxLines) {
@@ -42,7 +68,7 @@ function chatBoxScrollUp() {
}
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function chatBoxScrollDown() {
if(bottomMessageIndex < chatBoxHistory.length-1) {
@@ -51,7 +77,7 @@ function chatBoxScrollDown() {
}
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function clearChatBox() {
for(let i = 0 ; i <= maxChatBoxLines ; i++) {
@@ -59,7 +85,7 @@ function clearChatBox() {
}
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function updateChatBox() {
clearChatBox();
@@ -72,4 +98,4 @@ function updateChatBox() {
}
}
-// ---------------------------------------------------------------------------
\ No newline at end of file
+// ===========================================================================
\ No newline at end of file
diff --git a/scripts/client/event.js b/scripts/client/event.js
new file mode 100644
index 00000000..399dc8c4
--- /dev/null
+++ b/scripts/client/event.js
@@ -0,0 +1,237 @@
+// ===========================================================================
+// Asshat-Gaming Roleplay
+// https://github.com/VortrexFTW/gtac_asshat_rp
+// Copyright (c) 2021 Asshat-Gaming (https://asshatgaming.com)
+// ===========================================================================
+// FILE: event.js
+// DESC: Provides handlers for built in GTAC and Asshat-Gaming created events
+// TYPE: Client (JavaScript)
+// ===========================================================================
+
+function initEventScript() {
+ logToConsole(LOG_DEBUG, "[Asshat.Event]: Initializing event script ...");
+ addCustomEvents();
+ addAllEventHandlers();
+ logToConsole(LOG_DEBUG, "[Asshat.Event]: Event script initialized!");
+}
+
+// ===========================================================================
+
+function addCustomEvents() {
+ addEvent("OnLocalPlayerEnterSphere", 1);
+ addEvent("OnLocalPlayerExitSphere", 1);
+ addEvent("OnLocalPlayerEnteredVehicle", 1);
+ addEvent("OnLocalPlayerExitedVehicle", 1);
+ addEvent("OnLocalPlayerSwitchWeapon", 2);
+}
+
+// ===========================================================================
+
+function addAllEventHandlers() {
+ bindEventHandler("OnResourceStart", thisResource, onResourceStart);
+ bindEventHandler("OnResourceReady", thisResource, onResourceReady);
+ bindEventHandler("OnResourceStop", thisResource, onResourceStop);
+
+ addEventHandler("OnProcess", onProcess);
+ addEventHandler("OnKeyUp", onKeyUp);
+ addEventHandler("OnDrawnHUD", onDrawnHUD);
+
+ addEventHandler("OnPedWasted", onPedWasted);
+
+ addEventHandler("OnElementStreamIn", onElementStreamIn);
+
+ addEventHandler("OnLocalPlayerEnteredVehicle", onLocalPlayerEnteredVehicle);
+ addEventHandler("OnLocalPlayerExitedVehicle", onLocalPlayerExitedVehicle);
+ addEventHandler("OnLocalPlayerEnterSphere", onLocalPlayerEnterSphere);
+ addEventHandler("OnLocalPlayerExitSphere", onLocalPlayerExitSphere);
+ addEventHandler("OnLocalPlayerSwitchWeapon", onLocalPlayerSwitchWeapon);
+
+ addEventHandler("OnPedInflictDamage", onPedInflictDamage);
+
+ addEventHandler("OnLostFocus", onLostFocus);
+ addEventHandler("OnFocus", onFocus);
+
+ addEventHandler("OnCameraProcess", onCameraProcess);
+}
+
+// ===========================================================================
+
+function onResourceStart(event, resource) {
+ sendResourceStartedSignalToServer();
+ //closeAllGarages();
+
+ if(getGame() == GAME_GTA_SA) {
+ gta.setDefaultInteriors(false);
+ }
+
+ garbageCollectorInterval = setInterval(collectAllGarbage, 1000*60);
+}
+
+// ===========================================================================
+
+function onResourceStop(event, resource) {
+ sendResourceStoppedSignalToServer();
+}
+
+// ===========================================================================
+
+function onResourceReady(event, resource) {
+ sendResourceReadySignalToServer();
+ //closeAllGarages();
+}
+
+// ===========================================================================
+
+function onProcess(event, deltaTime) {
+ if(gta.game != GAME_GTA_IV) {
+ gta.clearMessages();
+ }
+
+ if(localPlayer == null) {
+ return false;
+ }
+
+ if(!isSpawned) {
+ return false;
+ }
+
+ processSync();
+ destroyAutoCreatedPickups();
+ processLocalPlayerControlState();
+ clearLocalPlayerWantedLevel();
+ processLocalPlayerVehicleControlState();
+ processLocalPlayerSphereEntryExitHandling();
+ processLocalPlayerVehicleEntryExitHandling();
+ processJobRouteSphere();
+ forceLocalPlayerEquippedWeaponItem();
+ processWantedLevelReset();
+}
+
+// ===========================================================================
+
+function onKeyUp(event, keyCode, scanCode, keyModifiers) {
+ processSkinSelectKeyPress(keyCode);
+}
+
+// ===========================================================================
+
+function onDrawnHUD(event) {
+ if(!renderHUD) {
+ return false;
+ }
+
+ if(localPlayer == null) {
+ return false;
+ }
+
+ //if(gta.game == GAME_GTA_VC) {
+ // return false;
+ //}
+
+ processSmallGameMessageRendering();
+ processScoreBoardRendering();
+ processLabelRendering();
+ processLogoRendering();
+ processItemActionRendering();
+ processSkinSelectRendering();
+ processNameTagRendering();
+}
+
+// ===========================================================================
+
+function onPedWasted(event, wastedPed, killerPed, weapon, pedPiece) {
+ logToConsole(LOG_DEBUG, `[Asshat.Event] Ped ${wastedPed.name} died`);
+ wastedPed.clearWeapons();
+}
+
+// ===========================================================================
+
+function onElementStreamIn(event, element) {
+ syncElementProperties(element);
+}
+
+// ===========================================================================
+
+function onLocalPlayerExitedVehicle(event, vehicle, seat) {
+ logToConsole(LOG_DEBUG, `[Asshat.Event] Local player exited vehicle`);
+ triggerNetworkEvent("ag.onPlayerExitVehicle", getVehicleForNetworkEvent(vehicle), seat);
+ if(inVehicleSeat) {
+ parkedVehiclePosition = false;
+ parkedVehicleHeading = false;
+ }
+}
+
+// ===========================================================================
+
+function onLocalPlayerEnteredVehicle(event, vehicle, seat) {
+ logToConsole(LOG_DEBUG, `[Asshat.Event] Local player entered vehicle`);
+ triggerNetworkEvent("ag.onPlayerEnterVehicle", getVehicleForNetworkEvent(vehicle), seat);
+
+ if(inVehicleSeat == 0) {
+ if(inVehicle.owner != -1) {
+ inVehicle.engine = false;
+ if(!inVehicle.engine) {
+ parkedVehiclePosition = inVehicle.position;
+ parkedVehicleHeading = inVehicle.heading;
+ }
+ }
+ }
+}
+
+// ===========================================================================
+
+function onPedInflictDamage(event, damagedEntity, damagerEntity, weaponId, healthLoss, pedPiece) {
+ let damagerEntityString = (!isNull(damagedEntity)) ? `${damagerEntity.name} (${damagerEntity.name}, ${damagerEntity.type} - ${typeof damagerEntity})` : `Unknown ped`;
+ let damagedEntityString = (!isNull(damagedEntity)) ? `${damagedEntity.name} (${damagedEntity.name}, ${damagedEntity.type} - ${typeof damagedEntity})` : `Unknown ped`;
+
+ logToConsole(LOG_DEBUG, `[Asshat.Event] ${damagerEntityString} damaged ${damagedEntityString}'s '${pedPiece} with weapon ${weaponId}`);
+ if(!isNull(damagedEntity) && !isNull(damagerEntity)) {
+ if(damagedEntity.isType(ELEMENT_PLAYER)) {
+ if(damagedEntity == localPlayer) {
+ if(!weaponDamageEnabled[damagerEntity.name]) {
+ event.preventDefault();
+ triggerNetworkEvent("ag.weaponDamage", damagerEntity.name, weaponId, pedPiece, healthLoss);
+ }
+ }
+ }
+ }
+}
+
+// ===========================================================================
+
+function onLocalPlayerEnterSphere(event, sphere) {
+ logToConsole(LOG_DEBUG, `[Asshat.Event] Local player entered sphere`);
+ if(sphere == jobRouteStopSphere) {
+ enteredJobRouteSphere();
+ }
+}
+
+// ===========================================================================
+
+function onLocalPlayerExitSphere(event, sphere) {
+ logToConsole(LOG_DEBUG, `[Asshat.Event] Local player exited sphere`);
+}
+
+// ===========================================================================
+
+function onLostFocus(event) {
+ processLostFocusAFK();
+}
+
+// ===========================================================================
+
+function onFocus(event) {
+ processFocusAFK();
+}
+
+// ===========================================================================
+
+function onLocalPlayerSwitchWeapon(oldWeapon, newWeapon) {
+}
+
+// ===========================================================================
+
+function onCameraProcess(event) {
+}
+
+// ===========================================================================
\ No newline at end of file
diff --git a/scripts/client/gui.js b/scripts/client/gui.js
index c34d8dda..8003fe6b 100644
--- a/scripts/client/gui.js
+++ b/scripts/client/gui.js
@@ -1,8 +1,8 @@
// ===========================================================================
// Asshat-Gaming Roleplay
// https://github.com/VortrexFTW/gtac_asshat_rp
-// Copyright (c) 2020 Asshat-Gaming (https://asshatgaming.com)
-// ---------------------------------------------------------------------------
+// Copyright (c) 2021 Asshat-Gaming (https://asshatgaming.com)
+// ===========================================================================
// FILE: gui.js
// DESC: Provides GUI functionality and styles (using MexUI)
// TYPE: Client (JavaScript)
@@ -25,6 +25,8 @@ let windowTitleAlpha = 200;
let buttonAlpha = 200;
let textInputAlpha = 200;
+// ===========================================================================
+
let login = {
window: null,
logoImage: null,
@@ -34,6 +36,8 @@ let login = {
loginButton: null,
};
+// ===========================================================================
+
let twoFactorAuth = {
window: null,
logoImage: null,
@@ -44,6 +48,8 @@ let twoFactorAuth = {
submitButton: null,
};
+// ===========================================================================
+
let register = {
window: null,
logoImage: null,
@@ -54,6 +60,8 @@ let register = {
registerButton: null,
};
+// ===========================================================================
+
let newCharacter = {
window: null,
firstNameInput: null,
@@ -61,21 +69,34 @@ let newCharacter = {
skinDropDown: null,
spawnAreaDropDown: null,
createButton: null,
- skinImage: null,
};
+// ===========================================================================
+
let errorDialog = {
window: null,
messageLabel: null,
okayButton: null,
};
+// ===========================================================================
+
let infoDialog = {
window: null,
messageLabel: null,
okayButton: null,
};
+// ===========================================================================
+
+let listDialog = {
+ window: null,
+ messageLabel: null,
+ listGrid: null,
+};
+
+// ===========================================================================
+
let yesNoDialog = {
window: null,
messageLabel: null,
@@ -83,985 +104,22 @@ let yesNoDialog = {
noButton: null,
};
+// ===========================================================================
+
let characterSelect = {
window: null,
skinImage: null,
nameText: null,
- dateOfBirthText: null,
- placeOfOriginText: null,
+ cashText: null,
+ clanText: null,
+ lastPlayedText: null,
previousCharacterButton: null,
nextCharacterButton: null,
selectCharacterButton: null,
newCharacterButton: null,
};
-let skinNames = [
- [],
- [ // GTA III
- //[0, "Claude", "Skin000.png"],
- //[1, "Police Officer", "Skin001.png"],
- //[2, "SWAT Officer", "Skin002.png"],
- //[3, "FBI Agent", "Skin003.png"],
- //[4, "Army Soldier", "Skin004.png"],
- //[5, "Paramedic", "Skin005.png"],
- //[6, "Firefighter", "Skin006.png"],
- [7, "Wise Guy", "Skin007.png"],
- //[8, "Taxi Driver", "Skin008.png"],
- [9, "Pimp", "Skin009.png"],
- [10, "Mafia Member", "Skin010.png"],
- [11, "Mafia Member", "Skin011.png"],
- [12, "Triad Member", "Skin012.png"],
- [13, "Triad Member", "Skin013.png"],
- [14, "Diablo Member", "Skin014.png"],
- [15, "Diablo Member", "Skin015.png"],
- [16, "Yakuza Member", "Skin016.png"],
- [17, "Yakuza Member", "Skin017.png"],
- [18, "Yardie Member", "Skin018.png"],
- [19, "Yardie Member", "Skin019.png"],
- [20, "Cartel Soldier", "Skin020.png"],
- [21, "Cartel Soldier", "Skin021.png"],
- [22, "Red Jacks Thug", "Skin022.png"],
- [23, "Purple Nines Thug", "Skin023.png"],
- [24, "Street Criminal", "Skin024.png"],
- [25, "Street Criminal", "Skin025.png"],
- [30, "Male Client", "Skin030.png"],
- [31, "Random Guy", "Skin031.png"],
- [32, "Vacationist", "Skin032.png"],
- [33, "Dj", "Skin033.png"],
- [34, "Young Woman", "Skin034.png"],
- [35, "Young Woman", "Skin035.png"],
- [36, "Business Woman", "Skin036.png"],
- [37, "Elder Woman", "Skin037.png"],
- [38, "Elder Woman", "Skin038.png"],
- [39, "Prostitute", "Skin039.png"],
- [40, "Prostitute", "Skin040.png"],
- [41, "Random Guy", "Skin041.png"],
- [42, "Diseased Man", "Skin042.png"],
- [43, "Deseased Woman", "Skin043.png"],
- [44, "Young Woman", "Skin044.png"],
- [45, "Old Man", "Skin045.png"],
- [46, "Random Guy", "Skin046.png"],
- [47, "Old Woman", "Skin047.png"],
- [48, "Old Woman", "Skin048.png"],
- [49, "Old Man", "Skin049.png"],
- [50, "Random Guy", "Skin050.png"],
- [51, "Old Woman", "Skin051.png"],
- [52, "Young Woman", "Skin052.png"],
- [53, "Docks Worker", "Skin053.png"],
- [54, "Docks Worker", "Skin054.png"],
- [55, "Male Street Bum", "Skin055.png"],
- [56, "Female Street Bum", "Skin056.png"],
- [57, "Delivery Guy", "Skin057.png"],
- [58, "Delivery Guy", "Skin058.png"],
- [59, "Business Man", "Skin059.png"],
- [60, "Marty Chonks", "Skin060.png"],
- [61, "CIA Agent", "Skin061.png"],
- [62, "Female Client", "Skin062.png"],
- [63, "Young Woman", "Skin063.png"],
- [64, "Business Woman", "Skin064.png"],
- [65, "Business Man", "Skin065.png"],
- [66, "Female Client", "Skin066.png"],
- [67, "Male Steward", "Skin067.png"],
- [68, "Female Steward", "Skin068.png"],
- [69, "Male Cocks Fan", "Skin069.png"],
- [70, "Male Cocks Fan", "Skin070.png"],
- [71, "Female Cocks Fan", "Skin071.png"],
- [72, "Male Paramedics Assistant", "Skin072.png"],
- [73, "Female Paramedics Assistant", "Skin073.png"],
- [74, "Construction Worker", "Skin074.png"],
- [75, "Construction Worker", "Skin075.png"],
- [76, "Zip Customer", "Skin076.png"],
- [77, "Party Woman", "Skin077.png"],
- [78, "Party Woman", "Skin078.png"],
- [80, "Female College Student", "Skin080.png"],
- [81, "Old Man", "Skin081.png"],
- [82, "Female Jogger", "Skin082.png"],
- [83, "Asuka Kasen", "Skin083.png"],
- [84, "Spank Suicide Bomber", "Skin084.png"],
- [85, "Salvatore's Butler", "Skin085.png"],
- [86, "Catalina", "Skin086.png"],
- [87, "Lee Chong", "Skin087.png"],
- [88, "Colombian Cartel Member", "Skin088.png"],
- [89, "Colombian Cartel Member", "Skin089.png"],
- [90, "Colombian Cartel Member", "Skin090.png"],
- [91, "Colombian Cartel Member", "Skin091.png"],
- //[92, "Police Officer", "Skin092.png"],
- [93, "Curly Bob", "Skin093.png"],
- [94, "Phil Cassidy", "Skin094.png"],
- [95, "Detective", "Skin095.png"],
- [96, "8-Ball", "Skin096.png"],
- [97, "8-Ball", "Skin097.png"],
- [98, "Salvatore Leone", "Skin098.png"],
- [99, "Mafia Member", "Skin099.png"],
- [100, "Joey Leone", "Skin100.png"],
- [101, "Joey Leone", "Skin101.png"],
- [102, "Bar Owner", "Skin102.png"],
- [103, "Kenji Kasen", "Skin103.png"],
- [104, "Mike Forelli", "Skin104.png"],
- [105, "Donald Love", "Skin105.png"],
- [106, "Donald Love", "Skin106.png"],
- [107, "Luigi Goterelli", "Skin107.png"],
- [108, "Maria Latore", "Skin108.png"],
- [109, "Mickey Hamfists", "Skin109.png"],
- [110, "Miguel", "Skin110.png"],
- [111, "Misty", "Skin111.png"],
- [112, "Old Oriental Gentleman", "Skin112.png"],
- [113, "Old Oriental Gentleman", "Skin113.png"],
- [114, "Old Oriental Gentleman", "Skin114.png"],
- [115, "Ray Machowski", "Skin115.png"],
- [116, "Mafia Member", "Skin116.png"],
- [118, "Tanner", "Skin118.png"],
- [119, "Toni Cipriani", "Skin119.png"],
- [120, "Darkel", "Skin120.png"],
- //[121, "Chuff Security Officer", "Skin121.png"]
- ],
- [ // GTA Vice City
- //[0, "Tommy Vercetti", false],
- //[1, "Police Officer", false],
- //[2, "SWAT Officer", false],
- //[3, "FBI Agent", false],
- //[4, "Army Soldier", false],
- //[5, "Paramedic", false],
- //[6, "Fireman", false],
- [7, "Golfer", false],
- //[8, "INVALID", false],
- [9, "Random Lady", false],
- [10, "Bum", false],
- [11, "Greaser", false],
- [12, "Random Guy", false],
- [13, "Random Guy", false],
- [14, "Random Lady", false],
- [15, "Random Guy", false],
- [16, "Random Guy", false],
- [17, "Beach Girl", false],
- [18, "Fat Beach Lady", false],
- [19, "Beach Guy", false],
- [20, "Fat Beach Guy", false],
- [21, "Random Lady", false],
- [22, "Random Lady", false],
- [23, "Random Lady", false],
- [24, "Prostitute", false],
- [25, "Bum", false],
- [26, "Bum", false],
- [27, "Random Guy", false],
- [28, "Taxi Driver", false],
- [29, "Haitian", false],
- [30, "Criminal", false],
- [31, "Random Lady", false],
- [32, "Random Lady", false],
- [33, "Random Guy", false],
- [34, "Random Guy", false],
- [35, "Random Lady", false],
- [36, "Random Lady", false],
- [37, "Random Guy", false],
- [38, "Beach Lady", false],
- [39, "Beach Guy", false],
- [40, "Beach Lady", false],
- [41, "Beach Guy", false],
- [42, "Random Guy", false],
- [43, "Prostitute", false],
- [44, "Bum", false],
- [45, "Bum", false],
- [46, "Random Guy", false],
- [47, "Random Guy", false],
- [48, "Punk", false],
- [49, "Prostitute", false],
- [50, "Random Old Lady", false],
- [51, "Punk", false],
- [52, "Random Guy", false],
- [53, "Random Lady", false],
- [54, "Random Lady", false],
- [55, "Random Guy", false],
- [56, "Random Guy", false],
- [57, "Beach Lady", false],
- [58, "Beach Guy", false],
- [59, "Beach Lady", false],
- [60, "Beach Guy", false],
- [61, "Construction Worker", false],
- [62, "Golfer", false],
- [63, "Golfer", false],
- [64, "Golfer", false],
- [65, "Beach Lady", false],
- [66, "Beach Guy", false],
- [67, "Random Lady", false],
- [68, "Random Guy", false],
- [69, "Random Guy", false],
- [70, "Prostitute", false],
- [71, "Bum Lady", false],
- [72, "Random Guy", false],
- [73, "Random Guy", false],
- [74, "Taxi Driver", false],
- [75, "Random Woman", false],
- [76, "Skater Guy", false],
- [77, "Beach Lady", false],
- [78, "Skater Guy", false],
- [79, "Young Woman Shopper", false],
- [80, "Old Women Shopper", false],
- [81, "Tourist", false],
- [82, "Tourist", false],
- [83, "Cuban", false],
- [84, "Cuban", false],
- [85, "Haitian", false],
- [86, "Haitian", false],
- [87, "Shark", false],
- [88, "Shark", false],
- [89, "Diaz Guy", false],
- [90, "Diaz Guy", false],
- //[91, "Security Guard", false],
- //[92, "Security Guard", false],
- [93, "Biker", false],
- [94, "Biker", false],
- [95, "Vercetti Guy", false],
- [96, "Vercetti Guy", false],
- //[97, "Undercover Cop", false],
- //[98, "Undercover Cop", false],
- //[99, "Undercover Cop", false],
- //[100, "Undercover Cop ", false],
- //[101, "Undercover Cop", false],
- //[102, "Undercover Cop", false],
- [103, "Random Guy", false],
- [104, "Bodyguard", false],
- [105, "Prostitute", false],
- [106, "Prostitute", false],
- [107, "Ricardo Diaz", false],
- [108, "Love Fist Guy", false],
- [109, "Ken Rosenburg", false],
- [110, "Candy Suxx", false],
- [111, "Hilary", false],
- [112, "Love Fist", false],
- [113, "Phil", false],
- [114, "Rockstar Guy", false],
- [115, "Sonny", false],
- [116, "Lance", false],
- [117, "Mercedes", false],
- [118, "Love Fist", false],
- [119, "Alex Scrub", false],
- //[120, "Officer Lance Vance", false],
- [121, "Lance Vance", false],
- [122, "Cortez", false],
- //[123, "SWAT 2", false],
- [124, "Columbian", false],
- [125, "Hilary", false],
- [126, "Mercedes", false],
- [127, "Cam", false],
- [128, "Cam", false],
- [129, "Phil", false],
- [130, "Phil", false],
- [131, "Bodyguard", false],
- [132, "Pizza Worker", false],
- [133, "Taxi Driver", false],
- [134, "Taxi Driver", false],
- [135, "Sailor", false],
- [136, "Sailor", false],
- [137, "Sailor", false],
- [138, "Chef", false],
- [139, "Criminal", false],
- [140, "French Guy", false],
- [141, "Worker", false],
- [142, "Haitian", false],
- [143, "Waitress", false],
- [144, "Forelli Member", false],
- [145, "Forelli Member", false],
- [146, "Forelli Member", false],
- [147, "Columbian", false],
- [148, "Random Guy", false],
- [149, "Beach Guy", false],
- [150, "Random Guy", false],
- [151, "Random Guy", false],
- [152, "Random Guy", false],
- [153, "Drag Queen", false],
- [154, "Diaz Traitor", false],
- [155, "Random Guy", false],
- [156, "Random Guy", false],
- [157, "Stripper", false],
- [158, "Stripper", false],
- [159, "Stripper", false],
- [160, "Store Clerk", false],
- [161, "Tommy Vercetti", false],
- [162, "Tommy Vercetti (Business Suit)", false],
- [163, "Tommy Vercetti (SpandEx Overalls)", false],
- [164, "Tommy Vercetti (Golfer)", false],
- [165, "Tommy Vercetti (Cuban)", false],
- //[166, "Tommy Vercetti (Cop)", false],
- [167, "Tommy Vercetti (Robbery Suit)", false],
- [168, "Tommy Vercetti (T-Shirt and Jeans)", false],
- [169, "Tommy Vercetti (Striped Suit)", false],
- [170, "Tommy Vercetti (Black Tracksuit)", false],
- [171, "Tommy Vercetti (Red Tracksuit)", false],
- [172, "Club Bouncer", false],
- [173, "Club Bouncer", false],
- [174, "Stripclub Dancer", false],
- [175, "Random Guy", false],
- [176, "Stripclub Dancer", false],
- [177, "Stripclub Dancer", false],
- [178, "Stripclub Dancer", false],
- [179, "Gang Member", false],
- [180, "Tommy Vercetti (Endgame T-Shirt)", false],
- [181, "Forelli Thug", false],
- [182, "Forelli Thug", false],
- [183, "Random Lady", false],
- [184, "Gang Member", false],
- [185, "Party Waitress", false],
- [186, "Kent Paul", false],
- [187, "Big Head Taxi Driver", false],
- ],
-
- [ // GTA San Andreas
- //[0, "Carl 'CJ' Johnson", false],
- [1, "The Truth", false],
- [2, "Maccer", false],
- [6, "Taxi Driver/Train Driver", false],
- [9, "Normal Ped", false],
- [10, "Old Woman", false],
- [11, "Casino Croupier", false],
- [12, "Rich Woman", false],
- [13, "Street Girl", false],
- [14, "Normal Ped", false],
- [15, "Mr.Whittaker (RS Haul Owner)", false],
- [16, "Airport Ground Worker", false],
- [17, "Businessman", false],
- [18, "Beach Visitor", false],
- [19, "DJ", false],
- [20, "Rich Guy (Madd Doggs Manager)", false],
- [21, "Normal Ped", false],
- [22, "Normal Ped", false],
- [23, "Bmxer", false],
- [24, "Madd Dogg Bodyguard", false],
- [25, "Madd Dogg Bodyguard", false],
- [26, "Backpacker", false],
- [27, "Construction Worker", false],
- [28, "Drug Dealer", false],
- [29, "Drug Dealer", false],
- [30, "Drug Dealer", false],
- [31, "Farm-Town Inhabitant", false],
- [32, "Farm-Town Inhabitant", false],
- [33, "Farm-Town Inhabitant", false],
- [34, "Farm-Town Inhabitant", false],
- [35, "Gardener", false],
- [36, "Golfer", false],
- [37, "Golfer", false],
- [38, "Normal Ped", false],
- [39, "Normal Ped", false],
- [40, "Normal Ped", false],
- [41, "Normal Ped", false],
- [43, "Normal Ped", false],
- [44, "Normal Ped", false],
- [45, "Beach Visitor", false],
- [46, "Normal Ped", false],
- [47, "Normal Ped", false],
- [48, "Normal Ped", false],
- [49, "Snakehead (Da Nang)", false],
- [50, "Mechanic", false],
- [51, "Mountain Biker", false],
- [52, "Mountain Biker", false],
- [53, "Unknown", false],
- [54, "Normal Ped", false],
- [55, "Normal Ped", false],
- [56, "Normal Ped", false],
- [57, "Oriental Ped", false],
- [58, "Oriental Ped", false],
- [59, "Normal Ped", false],
- [60, "Normal Ped", false],
- [61, "Pilot", false],
- [62, "Colonel Fuhrberger", false],
- [63, "Prostitute", false],
- [64, "Prostitute", false],
- [66, "Pool Player", false],
- [67, "Pool Player", false],
- [68, "Priest/Preacher", false],
- [69, "Normal Ped", false],
- [70, "Scientist", false],
- [71, "Security Guard", false],
- [72, "Hippy", false],
- [73, "Hippy", false],
- [75, "Prostitute", false],
- [76, "Stewardess", false],
- [77, "Homeless", false],
- [78, "Homeless", false],
- [79, "Homeless", false],
- [80, "Boxer", false],
- [81, "Boxer", false],
- [82, "Black Elvis", false],
- [83, "White Elvis", false],
- [84, "Blue Elvis", false],
- [85, "Prostitute", false],
- [87, "Stripper", false],
- [88, "Normal Ped", false],
- [89, "Normal Ped", false],
- [90, "Jogger", false],
- [91, "Rich Woman", false],
- [92, "Rollerskater", false],
- [93, "Normal Ped", false],
- [94, "Normal Ped", false],
- [95, "Normal Ped", false],
- [96, "Jogger", false],
- [97, "Lifeguard", false],
- [98, "Normal Ped", false],
- [99, "Rollerskater", false],
- [100, "Biker", false],
- [101, "Normal Ped", false],
- [102, "Ballas Gang Member", false],
- [103, "Ballas Gang Member", false],
- [104, "Ballas Gang Member", false],
- [105, "Grove Street Families Gang Member", false],
- [106, "Grove Street Families Gang Member", false],
- [107, "Grove Street Families Gang Member", false],
- [108, "Los Santos Vagos Gang Member", false],
- [109, "Los Santos Vagos Gang Member", false],
- [110, "Los Santos Vagos Gang Member", false],
- [111, "Russian Mafioso", false],
- [112, "Russian Mafioso", false],
- [113, "Russian Mafioso", false],
- [114, "Varios Los Aztecas Gang Member", false],
- [115, "Varios Los Aztecas Gang Member", false],
- [116, "Varios Los Aztecas Gang Member", false],
- [117, "Triad", false],
- [118, "Triad", false],
- [120, "Triad Boss", false],
- [121, "Da Nang Boy", false],
- [122, "Da Nang Boy", false],
- [123, "Da Nang Boy", false],
- [124, "Italian Mafioso", false],
- [125, "Italian Mafioso", false],
- [126, "Italian Mafioso", false],
- [127, "Italian Mafioso", false],
- [128, "Farm Inhabitant", false],
- [129, "Farm Inhabitant", false],
- [130, "Farm Inhabitant", false],
- [131, "Farm Inhabitant", false],
- [132, "Farm Inhabitant", false],
- [133, "Farm Inhabitant", false],
- [134, "Homeless", false],
- [135, "Homeless", false],
- [136, "Normal Ped", false],
- [137, "Homeless", false],
- [138, "Beach Visitor", false],
- [139, "Beach Visitor", false],
- [140, "Beach Visitor", false],
- [141, "Businesswoman", false],
- [142, "Taxi Driver", false],
- [143, "Crack Maker", false],
- [144, "Crack Maker", false],
- [145, "Crack Maker", false],
- [146, "Crack Maker", false],
- [147, "Businessman", false],
- [148, "Businesswoman", false],
- //[149, "INVALID", false],
- [150, "Businesswoman", false],
- [151, "Normal Ped", false],
- [152, "Prostitute", false],
- [153, "Construction Worker", false],
- [154, "Beach Visitor", false],
- [155, "Well Stacked Pizza Worker", false],
- [156, "Barber", false],
- [157, "Hillbilly", false],
- [158, "Farmer", false],
- [159, "Hillbilly", false],
- [160, "Hillbilly", false],
- [161, "Farmer", false],
- [162, "Hillbilly", false],
- [163, "Black Bouncer", false],
- [164, "White Bouncer", false],
- [165, "White MIB Agent", false],
- [166, "Black MIB Agent", false],
- [167, "Cluckin Bell Worker", false],
- [168, "Hotdog/Chilli Dog Vendor", false],
- [169, "Normal Ped", false],
- [170, "Normal Ped", false],
- [171, "Blackjack Dealer", false],
- [172, "Casino Croupier", false],
- [173, "San Fierro Rifa", false],
- [174, "San Fierro Rifa", false],
- [175, "San Fierro Rifa", false],
- [176, "Barber", false],
- [177, "Barber", false],
- [178, "Whore", false],
- [179, "Ammunation Salesman", false],
- [180, "Tattoo Artist", false],
- [181, "Punk", false],
- [182, "Cab Driver", false],
- [183, "Normal Ped", false],
- [184, "Normal Ped", false],
- [185, "Normal Ped", false],
- [186, "Normal Ped", false],
- [187, "Businessman", false],
- [188, "Normal Ped", false],
- [189, "Valet", false],
- [190, "Barbara Schternvart", false],
- [191, "Helena Wankstein", false],
- [192, "Michelle Cannes", false],
- [193, "Katie Zhan", false],
- [194, "Millie Perkins", false],
- [195, "Denise Robinson", false],
- [196, "Farm-Town Inhabitant", false],
- [197, "Hillbilly", false],
- [198, "Farm-Town Inhabitant", false],
- [199, "Farm-Town Inhabitant", false],
- [200, "Hillbilly", false],
- [201, "Farmer", false],
- [202, "Farmer", false],
- [203, "Karate Teacher", false],
- [204, "Karate Teacher", false],
- [205, "Burger Shot Cashier", false],
- [206, "Cab Driver", false],
- [207, "Prostitute", false],
- [209, "Oriental Noodle Stand Vendor", false],
- [210, "Oriental Boating School Instructor", false],
- [211, "Clothes Shop Staff", false],
- [212, "Homeless", false],
- [213, "Weird Old Man", false],
- [214, "Waitress (Maria Latore)", false],
- [215, "Normal Ped", false],
- [216, "Normal Ped", false],
- [217, "Clothes Shop Staff", false],
- [218, "Normal Ped", false],
- [219, "Rich Woman", false],
- [220, "Cab Driver", false],
- [221, "Normal Ped", false],
- [222, "Normal Ped", false],
- [223, "Normal Ped", false],
- [224, "Normal Ped", false],
- [225, "Normal Ped", false],
- [226, "Normal Ped", false],
- [227, "Oriental Businessman", false],
- [228, "Oriental Ped", false],
- [229, "Oriental Ped", false],
- [230, "Homeless", false],
- [231, "Normal Ped", false],
- [232, "Normal Ped", false],
- [233, "Normal Ped", false],
- [234, "Cab Driver", false],
- [235, "Normal Ped", false],
- [236, "Normal Ped", false],
- [237, "Prostitute", false],
- [238, "Prostitute", false],
- [239, "Homeless", false],
- [240, "The D.A", false],
- [241, "Afro-American", false],
- [242, "Mexican", false],
- [243, "Prostitute", false],
- [244, "Stripper", false],
- [245, "Prostitute", false],
- [246, "Stripper", false],
- [247, "Biker", false],
- [248, "Biker", false],
- [249, "Pimp", false],
- [250, "Normal Ped", false],
- [251, "Lifeguard", false],
- [252, "Naked Valet", false],
- [253, "Bus Driver", false],
- [254, "Biker Drug Dealer", false],
- [255, "Chauffeur (Limo Driver)", false],
- [256, "Stripper", false],
- [257, "Stripper", false],
- [258, "Heckler", false],
- [259, "Heckler", false],
- [260, "Construction Worker", false],
- [261, "Cab Driver", false],
- [262, "Cab Driver", false],
- [263, "Normal Ped", false],
- [264, "Clown (Ice-Cream Van Driver)", false],
- //[265, "Officer Frank Tenpenny", false],
- //[266, "Officer Eddie Pulaski", false],
- //[267, "Officer Jimmy Hernandez", false],
- [268, "Dwaine/Dwayne", false],
- [269, "Melvin Big Smoke Harris (Mission)", false],
- [270, "Sean Sweet Johnson", false],
- [271, "Lance Ryder Wilson", false],
- [272, "Mafia Boss", false],
- //[274, "Paramedic", false],
- //[275, "Paramedic", false],
- //[276, "Paramedic", false],
- //[277, "Firefighter", false],
- //[278, "Firefighter", false],
- //[279, "Firefighter", false],
- //[280, "Los Santos Police Officer", false],
- //[281, "San Fierro Police Officer", false],
- //[282, "Las Venturas Police Officer", false],
- //[283, "County Sheriff", false],
- //[284, "Motorbike Cop", false],
- //[285, "S.W.A.T.", false],
- //[286, "Federal Agent", false],
- //[287, "Army Soldier", false],
- //[288, "Desert Sheriff", false],
- [290, "Ken Rosenberg", false],
- [291, "Kent Paul", false],
- [292, "Cesar Vialpando", false],
- [293, "Jeffery Og Loc Martin/Cross", false],
- [294, "Wu Zi Mu (Woozie)", false],
- [295, "Michael Toreno", false],
- [296, "Jizzy B.", false],
- [297, "Madd Dogg", false],
- [298, "Catalina", false],
- [299, "Claude Speed", false],
- [300, "Lance Ryder Wilson", false],
- [301, "Lance Ryder Wilson (robbery mask)", false],
- [302, "Emmet", false],
- [303, "Unknown", false],
- [304, "Denise", false],
- [305, "Jethro", false],
- [306, "Zero", false],
- [307, "T-Bone Mendez", false],
- [308, "Forelli", false],
- [309, "Mechanic", false],
- [310, "Barry Big Bear Thorne (Skinny)", false],
- [311, "Melvin Big Smoke Harris (Vest)", false],
- //[312, "Army Guy", false],
- [313, "Barry Big Bear Thorne (Fat)", false],
- ],
-
- [ // Underground
-
- ],
-
- [ // GTA IV
- //[-2020305438,"Male Multiplayer",false],
- //[-641875910,"Female Multiplayer",false],
- //[-1370810922,"MODEL_SUPERLOD",false],
- [1853617247,"Anna",false],
- [-1646893330,"Anthony",false],
- [1495769888,"Badman",false],
- [1500493064,"Bernie Crane",false],
- [1731510984,"Bledar",false],
- [422305098,"Brian",false],
- [-1729980128,"Brucie",false],
- [237511807,"Bulgarin",false],
- [88667657,"Charise",false],
- [-1328445565,"Charlie Undercover",false],
- [1343144208,"Clarence",false],
- [1468450703,"Dardan",false],
- [386513184,"Darko",false],
- [1169442297,"Derric",false],
- [237497537,"Dmitri",false],
- [-617264103,"Dwayne",false],
- [-1600585231,"Eddie",false],
- [57218969,"Faustin",false],
- [1710545037,"Francis",false],
- [1424670436,"French Tom",false],
- [2129490787,"Gordon",false],
- [-357652594,"Gracie",false],
- [980768434,"Hossan",false],
- [-835225126,"Ilyena",false],
- [-479595866,"Issac",false],
- [1166762483,"Ivan",false],
- [364686627,"Jay",false],
- [170756246,"Jason",false],
- [390357829,"Jeff",false],
- [-366421228,"Jimmy",false],
- [-911507684,"Johnny Klebitz",false],
- [-773750838,"Kate",false],
- [995576506,"Kenny",false],
- [1487004273,"Lil Jacob",false],
- [-1275031987,"Lil Jacob 2,",false],
- [-681942840,"Luca",false],
- [-492470690,"Luis",false],
- [-1040287406,"Mallorie",false],
- [-322700377,"Mam",false],
- [1445589009,"Manny",false],
- [411185872,"Marnie",false],
- [-807339118,"Mel",false],
- [735211577,"Michael",false],
- [-1080659212,"Michelle",false],
- [-636669566,"Mickey",false],
- [1690783035,"Packie",false],
- [-165448092,"Pathos",false],
- [-1947682830,"Petrovic",false],
- [-1826458934,"Phil Bell",false],
- [1794146792,"Playboy X",false],
- [954215094,"Ray Boccino",false],
- [-587324132,"Ricky",false],
- [-1992728631,"Roman",false],
- [558221221,"Roman 2,",false],
- [-17823883,"Sarah",false],
- [1384833284,"Tuna",false],
- [-1014976873,"Vinny Spaz",false],
- [896408642,"Vlad",false],
- [-301223260,"Black Street Thug 1,",false],
- [-1143910864,"Black Street Thug 2,",false],
- [869501081,"Black Street OG 1,",false],
- [632613980,"Black Street OG 1,",false],
- [-503930010,"Albanian Thug 1,",false],
- [-235584669,"Albanian Thug 2,",false],
- [207714363,"Albanian Thug 3,",false],
- [514268366,"Albanian Thug 4,",false],
- [43005364,"Biker 1,",false],
- [1346668127,"Biker 2,",false],
- [-1677255197,"Biker 3,",false],
- [-1461281345,"Biker 4,",false],
- [1574850459,"Biker 5,",false],
- [-1953289472,"Biker 6,",false],
- [280474699,"Irish Man 1,",false],
- [-19263344,"Irish Man 2,",false],
- [1844702918,"Irish Man 3,",false],
- [1609755055,"Jamaican OG 1,",false],
- [-330497431,"Jamaican OG 2,",false],
- [1117105909,"Jamaican OG 3,",false],
- [-1500397869,"Jamaican Thug 1,",false],
- [-881358690,"Jamaican Thug 2,",false],
- [1540383669,"Asian Man 1,",false],
- [764249904,"Asian Man 2,",false],
- [492147228,"Hispanic Man 1,",false],
- [-1926041127,"Hispanic Man 2,",false],
- [1168388225,"Hispanic Man 3,",false],
- [-1746774780,"Hispanic Man 4,",false],
- [-302362397,"Fat Italian Mafia Boss",false],
- [-1616890832,"Italian Mafia Boss",false],
- [64730935,"Italian Mafia Associate",false],
- [510389335,"Fat Italian Mafia Associate",false],
- [-1836006237,"Russian Thug 1,",false],
- [-2088164056,"Russian Thug 2,",false],
- [1976502708,"Russian Thug 3,",false],
- [1543404628,"Russian Thug 4,",false],
- [1865532596,"Russian Thug 5,",false],
- [431692232,"Russian Thug 6,",false],
- [1724587620,"Russian Thug 7,",false],
- [-1180674815,"Russian Thug 8,",false],
- [871281791,"Triad Boss 1,",false],
- [683712035,"Triad Boss 2,",false],
- [-1084007777,"Triad Member 3,",false],
- [-164935626,"Triad Member 4,",false],
- [-751071255,"Female Maid",false],
- [-109247258,"Female Binco Worker",false],
- [1366257926,"Female Bank Teller",false],
- [346338575,"Female Doctor",false],
- [1350216795,"Female Gym Worker",false],
- [924926104,"Female Burger Shot Worker",false],
- [-346378101,"Female Cluckin Bell Worker",false],
- [-2104311883,"Female Rockstar Cafe Worker",false],
- [212900845,"Female TW@ Cafe Worker",false],
- [-290070895,"Female Well Stacked Pizza Worker",false],
- [552542187,"Hooker",false],
- [996267216,"Hooker 2,",false],
- [-1193778389,"Nurse",false],
- [1113677074,"Stripper 1,",false],
- [1353709999,"Stripper 2,",false],
- [24233425,"Waitress",false],
- [-1761003415,"Alcoholic Man",false],
- [1075583233,"Armoured Truck Driver",false],
- [134077503,"Bus Driver",false],
- [757349871,"Generic Asian Man",false],
- [-1827421800,"Black Crackhead",false],
- [219393781,"Doctor (Scrubs)",false],
- [-1186940778,"Doctor",false],
- [375732086,"Doctor (Blood Covered Coat)",false],
- [2105015949,"Cook",false],
- [-200234085,"Italian Mob Enforcer",false],
- [800131009,"Factory Worker",false],
- [-999506922,"FIB Agent",false],
- [-1993909080,"Fat Delivery Driver",false],
- [610888851,"Fire Chief",false],
- [486302863,"Mercenary Soldier",false],
- [-778316080,"Helicopter Pilot",false],
- [624314380,"Hotel Doorman",false],
- [-1784833142,"Korean Cook",false],
- [-1852976689,"Lawyer 1,",false],
- [-1134712978,"Lawyer 2,",false],
- [379171768,"Loony Black Man",false],
- [-1945168882,"Pilot",false],
- [807236245,"Generic Man",false],
- [-284362863,"Postal Worker",false],
- [-1188246269,"Saxophone Player",false],
- [-1870989171,"Security Guard",false],
- [420915580,"Stadium Food Vendor",false],
- [1878085135,"Stadium Food Cook",false],
- [142730876,"Street Food Vendor",false],
- [-690681764,"Street Sweeper Driver",false],
- [8772846,"Taxi Driver",false],
- [1186270890,"Telephone Company Worker",false],
- [-379234846,"Tennis Player",false],
- [1159759556,"Train Conductor",false],
- [-142386662,"Homeless Black Man",false],
- [-46564867,"Trucker",false],
- [-1284047560,"Janitor",false],
- [22944263,"Hotel Doorman 2,",false],
- [1178487645,"Mob Boss",false],
- [-1464712858,"Airport Worker",false],
- [-2139064254,"Bartender",false],
- [-1780698891,"Biker Bouncer",false],
- [-409283472,"High End Club Bouncer",false],
- [-799229885,"Bowling Alley Worker",false],
- [-434183225,"Bowling Alley Worker 2,",false],
- [768442188,"Chinese Food Vendor",false],
- [676448572,"Club Security",false],
- [-722019798,"Construction Worker",false],
- [-1015957728,"Construction Worker 2,",false],
- [-714220780,"Construction Worker 3,",false],
- [-183203150,"Police Officer",false],
- [-1518937979,"Traffic Officer",false],
- [-370395528,"Fat Police Officer",false],
- [-1371133859,"Courier",false],
- [-573788283,"Cowboy 1,",false],
- [-1283406538,"Drug Dealer 1,",false],
- [1448755353,"Drug Dealer 2,",false],
- [989485,"Male Burger Shot Worker",false],
- [-1011530423,"Male Cluckin Bell Worker",false],
- [1979561477,"Male Rockstar Cafe Worker",false],
- [-786449781,"Male TW@ Cafe Worker",false],
- [206941425,"Male Well Stacked Pizza Worker",false],
- [-610224615,"Firefighter",false],
- [1136499716,"Garbage Collector",false],
- [897868981,"Goon",false],
- [-1902758612,"Male Gym Worker",false],
- [-356904519,"Mechanic 2,",false],
- [-1056268969,"Male Modo Worker",false],
- [1201610759,"Helicopter Pilot",false],
- [-151000142,"Perseus",false],
- [501136335,"Generic Male 1,",false],
- [186619473,"Generic Male 2,",false],
- [-111611196,"Generic Male 3,",false],
- [-1175077216,"Paramedic",false],
- [-1676937780,"Prisoner",false],
- [215190023,"Prisoner 2,",false],
- [1552970117,"Roman's Taxi Service Driver",false],
- [-1481923910,"Male Runner",false],
- [357919731,"Male Shop Assistant 1,",false],
- [-89302119,"State Trooper",false],
- [-1004762946,"SWAT",false],
- [-64233032,"Sword Swallower",false],
- [-1292254815,"Thief",false],
- [271284208,"Valet",false],
- [-186113957,"Vendor",false],
- [-2015686009,"French Tom",false],
- [1977784957,"Jim Fitz",false],
- [-203833294,"East European Woman",false],
- [189853472,"East European Woman 2,",false],
- [-349043578,"Woman",false],
- [-114937692,"Jersey Woman",false],
- [-1697333660,"Oriental Woman",false],
- [100706569,"Rich Woman",false],
- [155063868,"Business Woman 1,",false],
- [394310337,"Business Woman 2,",false],
- [1375728805,"Chinatown Woman",false],
- [-284229525,"Business Woman 3,",false],
- [677687516,"East European Woman 3,",false],
- [-1188238883,"Fat Black Woman",false],
- [-2075220936,"Jersey Woman 1,",false],
- [-1356924456,"Jersey Woman 2,",false],
- [812112483,"Fat Hispanic Woman 1,",false],
- [-129242580,"Fat Hispanic Woman 2,",false],
- [852423121,"White Manhattan Woman",false],
- [76551508,"Black Manhattan Woman",false],
- [-2118501976,"Old Asian Woman",false],
- [1616769823,"Old Rich Woman",false],
- [453889158,"Business Woman 4,",false],
- [824245375,"Asian Woman in Dress",false],
- [-1362442041,"Fat Black Bronx Woman",false],
- [-1788328884,"Random White Woman",false],
- [-1523915823,"Random Hispanic Woman",false],
- [-949987237,"Random Eastern European Woman",false],
- [-1926577323,"Random Black Woman",false],
- [168065679,"Black Harlem Woman 1,",false],
- [441464,"Fat Jersey Woman 1,",false],
- [54114008,"Fat Hispanic Woman 3,",false],
- [-292713088,"Hispanic Woman 1,",false],
- [1743814728,"Hispanic Woman 2,",false],
- [1670568326,"Manhattan Woman 1,",false],
- [1354281938,"Manhattan Woman 2,",false],
- [1056837725,"Manhattan Woman 1,",false],
- [-1193633577,"Asian Woman 1,",false],
- [713691120,"Black Woman 2,",false],
- [-1780385799,"Rich White Woman 1,",false],
- [-952185135,"Asian Woman",false],
- [1586287288,"Female Shopper 1,",false],
- [1848013291,"Female Shopper 2,",false],
- [-1702036227,"Female Shopper 3,",false],
- [1182843182,"Female Socialite 1,",false],
- [-900623157,"Street Woman 1,",false],
- [286007875,"Street Woman 2,",false],
- [1473654742,"Street Woman 3,",false],
- [-1850743775,"Street Woman 4,",false],
- [1290755317,"Street Woman 5,",false],
- [1872110126,"Street Woman 6,",false],
- [1754440500,"Tourist Woman 1,",false],
- [761763258,"MODEL_F_Y_VILLBO_01,",false],
- [-636579119,"Business Man 1,",false],
- [-1754526315,"Business Man 2,",false],
- [-1516474414,"Street Criminal 1,",false],
- [-1821258883,"Street Criminal 2,",false],
- [1952671026,"Obese Mafia Thug",false],
- [-1991603022,"Gay Man 1,",false],
- [-1080673049,"Homeless Bum 1,",false],
- [495499562,"Loony White Man 1,",false],
- [-1984134881,"MODEL_M_M_MIDTOWN_01,",false],
- [1063816580,"Business Man 2,",false],
- [208763854,"Eastern European Man 1,",false],
- [-1020237172,"Fat Black Man 2,",false],
- [1782277836,"MODEL_M_M_PINDUS_02,",false],
- [-1402442039,"Fat Italian Man 1,",false],
- [-1628417063,"Italian Man 2,",false],
- [1158569407,"Hispanic Man 1,",false],
- [1969438324,"Hispanic Man 2,",false],
- [1621955848,"Hispanic Man 3,",false],
- [-657489059,"Tourist Man 1,",false],
- [-1307068958,"Black Business Man 1,",false],
- [734334931,"Asian Man 3,",false],
- [1865082075,"MODEL_M_M_PRICH_01,",false],
- [-432593815,"MODEL_M_O_EASTEURO_01,",false],
- [-1639359785,"Hasidic Jewish Man 1,",false],
- [1656087115,"Old Man 1,",false],
- [2034185905,"MODEL_M_O_PEASTEURO_02,",false],
- [1316404726,"MODEL_M_O_PHARBRON_01,",false],
- [980990533,"MODEL_M_O_PJERSEY_01,",false],
- [-1298691925,"MODEL_M_O_STREET_01,",false],
- [243672348,"Old Business Man",false],
- [2085884255,"MODEL_M_Y_BOHO_01,",false],
- [221246143,"MODEL_M_Y_BOHOGUY_01,",false],
- [52357603,"MODEL_M_Y_BRONX_01,",false],
- [1530937394,"Black Business Man 2,",false],
- [690281432,"Black Business Man 3,",false],
- [-1149743642,"Asian Man 4,",false],
- [-314369597,"Chopshop Mechanic 1,",false],
- [-552829610,"Chopshop Mechanic 2,",false],
- [-1097188138,"MODEL_M_Y_DODGY_01,",false],
- [-1775659292,"MODEL_M_Y_DORK_02,",false],
- [1207402441,"MODEL_M_Y_DOWNTOWN_01,",false],
- [1500619449,"MODEL_M_Y_DOWNTOWN_02,",false],
- [594261682,"MODEL_M_Y_DOWNTOWN_03,",false],
- [-747824291,"MODEL_M_Y_GAYYOUNG",false],
- [-677160979,"MODEL_M_Y_GENSTREET_11,",false],
- [-1678614360,"MODEL_M_Y_GENSTREET_16,",false],
- [989044076,"MODEL_M_Y_GENSTREET_20,",false],
- [1180218190,"MODEL_M_Y_GENSTREET_34,",false],
- [-1420592428,"MODEL_M_Y_HARDMAN_01,",false],
- [-1222963415,"MODEL_M_Y_HARLEM_01,",false],
- [-1746153269,"MODEL_M_Y_HARLEM_02,",false],
- [2104499156,"MODEL_M_Y_HARLEM_04,",false],
- [-1874580889,"Hasidic Jewish Man 2,",false],
- [-1055386282,"MODEL_M_Y_LEASTSIDE_01,",false],
- [575808580,"MODEL_M_Y_PBRONX_01,",false],
- [-71980543,"MODEL_M_Y_PCOOL_01,",false],
- [-195159218,"MODEL_M_Y_PCOOL_02,",false],
- [697247370,"MODEL_M_Y_PEASTEURO_01,",false],
- [670406267,"MODEL_M_Y_PHARBRON_01,",false],
- [26615298,"MODEL_M_Y_PHARLEM_01,",false],
- [1542927558,"MODEL_M_Y_PJERSEY_01,",false],
- [-1806886352,"MODEL_M_Y_PLATIN_01,",false],
- [-1022920796,"MODEL_M_Y_PLATIN_02,",false],
- [-1326394505,"MODEL_M_Y_PLATIN_03,",false],
- [607901190,"MODEL_M_Y_PMANHAT_01,",false],
- [1968470106,"MODEL_M_Y_PMANHAT_02,",false],
- [-344136289,"MODEL_M_Y_PORIENT_01,",false],
- [560413584,"MODEL_M_Y_PQUEENS_01,",false],
- [1352017873,"MODEL_M_Y_PRICH_01,",false],
- [223726252,"MODEL_M_Y_PVILLBO_01,",false],
- [-1252681043,"MODEL_M_Y_PVILLBO_02,",false],
- [-1562020391,"MODEL_M_Y_PVILLBO_03,",false],
- [1223224881,"MODEL_M_Y_QUEENSBRIDGE",false],
- [-1220737489,"MODEL_M_Y_SHADY_02,",false],
- [1755322862,"MODEL_M_Y_SKATEBIKE_01,",false],
- [386690478,"MODEL_M_Y_SOHO_01,",false],
- [62496225,"MODEL_M_Y_STREET_01,",false],
- [523785438,"MODEL_M_Y_STREET_03,",false],
- [813889395,"MODEL_M_Y_STREET_04,",false],
- [-1552214124,"MODEL_M_Y_STREETBLK_02,",false],
- [-650575089,"MODEL_M_Y_STREETBLK_03,",false],
- [-740078918,"Street Punk 1,",false],
- [-1927496394,"Street Punk 2,",false],
- [1374242512,"Street Punk 3,",false],
- [-1139941790,"Tough Guy",false],
- [809067472,"Male Tourist",false],
- ]
-];
+// ===========================================================================
let placesOfOrigin = [
"Liberty City",
@@ -1076,11 +134,24 @@ let placesOfOrigin = [
"Other",
];
+// ===========================================================================
+
let characterData = [];
let currentCharacter = 0;
-app.init = function()
-{
+let inCharacterSelectScreen = false;
+let creatingCharacter = false;
+
+// ===========================================================================
+
+function initGUIScript() {
+ logToConsole(LOG_DEBUG, "[Asshat.GUI]: Initializing GUI script ...");
+ logToConsole(LOG_DEBUG, "[Asshat.GUI]: GUI script initialized!");
+}
+
+// ===========================================================================
+
+function initGUI() {
logToConsole(LOG_DEBUG, `[Asshat.GUI] Initializing GUI ...`);
logToConsole(LOG_DEBUG, `[Asshat.GUI] Creating login GUI ...`);
@@ -1160,7 +231,7 @@ app.init = function()
logToConsole(LOG_DEBUG, `[Asshat.GUI] Created login GUI`);
- // ------------------------------------------------------------------------------
+ // ===========================================================================
logToConsole(LOG_DEBUG, `[Asshat.GUI] Creating two factor auth GUI ...`);
twoFactorAuth.window = mexui.window(game.width/2-150, game.height/2-129, 300, 258, 'LOGIN', {
@@ -1238,203 +309,89 @@ app.init = function()
logToConsole(LOG_DEBUG, `[Asshat.GUI] Created two factor auth GUI`);
- // ------------------------------------------------------------------------------
+ // ===========================================================================
logToConsole(LOG_DEBUG, `[Asshat.GUI] Creating new character GUI ...`);
-
- newCharacter.window = mexui.window(game.width/2-215, game.height/2-83, 430, 166, 'New Character', {
+ newCharacter.window = mexui.window(game.width/2-130, game.height/2-100, 300, 200, 'Character Name', {
main: {
- backgroundColour: toColour(0, 0, 0, 120),
+ backgroundColour: toColour(0, 0, 0, windowAlpha),
transitionTime: 500,
},
title: {
- textSize: 11.0,
- textColour: toColour(0, 0, 0, 255),
+ textSize: 0.0,
+ textColour: toColour(0, 0, 0, 0),
backgroundColour: toColour(primaryColour[0], primaryColour[1], primaryColour[2], windowTitleAlpha),
},
icon: {
textSize: 0.0,
textColour: toColour(0, 0, 0, 0),
- backgroundColour: toColour(0, 0, 0, 0),
+ backgroundColour: toColour(primaryColour[0], primaryColour[1], primaryColour[2], windowTitleAlpha),
+ }
+ });
+ newCharacter.window.titleBarIconSize = toVector2(0,0);
+ newCharacter.window.titleBarHeight = 0;
+
+ newCharacter.window.image(115, 10, 65, 65, "files/images/main-logo.png", {
+ focused: {
+ borderColour: toColour(0, 0, 0, 0),
+ },
+ });
+
+ newCharacter.messageLabel = newCharacter.window.text(20, 75, 260, 20, 'Name your character', {
+ main: {
+ textSize: 10.0,
+ textAlign: 0.5,
+ textColour: toColour(200, 200, 200, 255),
+ textFont: robotoFont,
},
focused: {
borderColour: toColour(0, 0, 0, 0),
},
});
- newCharacter.firstNameInput = newCharacter.window.textInput(10, 40, 200, 25, '', {
+ newCharacter.firstNameInput = newCharacter.window.textInput(20, 100, 260, 25, '', {
main: {
- hover: {
- backgroundColour: toColour(0, 0, 0, 200),
- textColour: toColour(200, 200, 200, 255),
- textSize: 10.0,
- textFont: robotoFont,
- },
- backgroundColour: toColour(0, 0, 0, 200),
- textColour: toColour(200, 200, 200, 255),
- textSize: 10.0,
- textFont: robotoFont,
- },
- caret: {
- lineColour: toColour(255, 255, 255, 255),
- },
- placeholder: {
- backgroundColour: toColour(0, 0, 0, 200),
- textColour: toColour(200, 200, 200, 200),
- textSize: 10.0,
- textFont: robotoFont,
- },
- focused: {
- borderColour: toColour(focusedColour[0], focusedColour[1], focusedColour[2], textInputAlpha),
- },
- invalidValue: {
- borderColour: toColour(invalidValueColour[0], invalidValueColour[1], invalidValueColour[2], textInputAlpha),
- },
- });
- newCharacter.firstNameInput.placeholder = "First Name";
-
- newCharacter.lastNameInput = newCharacter.window.textInput(10, 70, 200, 25, '', {
- main: {
- hover: {
- backgroundColour: toColour(0, 0, 0, textInputAlpha),
- textColour: toColour(200, 200, 200, 255),
- textSize: 10.0,
- textFont: robotoFont,
- },
- backgroundColour: toColour(0, 0, 0, textInputAlpha),
- textColour: toColour(200, 200, 200, 255),
- textSize: 10.0,
- textFont: robotoFont,
- },
- caret: {
- lineColour: toColour(255, 255, 255, 255),
- },
- placeholder: {
- backgroundColour: toColour(0, 0, 0, textInputAlpha),
- textColour: toColour(150, 150, 150, 200),
- textSize: 10.0,
- textFont: robotoFont,
- },
- focused: {
- borderColour: toColour(focusedColour[0], focusedColour[1], focusedColour[2], 255),
- },
- invalidValue: {
- borderColour: toColour(invalidValueColour[0], invalidValueColour[1], invalidValueColour[2], 255),
- },
- });
- newCharacter.lastNameInput.placeholder = "Last Name";
-
- newCharacter.dateOfBirth = newCharacter.window.date(10, 130, 200, 25, 'Date of Birth', {
- main: {
- hover: {
- backgroundColour: toColour(0, 0, 0, 200),
- textColour: toColour(200, 200, 200, 255),
- textSize: 10.0,
- textFont: robotoFont,
- },
- backgroundColour: toColour(0, 0, 0, 200),
- textColour: toColour(200, 200, 200, 255),
- textSize: 10.0,
- textFont: robotoFont,
- },
- focused: {
- borderColour: toColour(focusedColour[0], focusedColour[1], focusedColour[2], 255),
- },
- invalidValue: {
- borderColour: toColour(invalidValueColour[0], invalidValueColour[1], invalidValueColour[2], 255),
- },
- });
-
- newCharacter.placeOfOrigin = newCharacter.window.dropDown(10, 100, 200, 25, 'Place of Origin', {
- main: {
- hover: {
- backgroundColour: toColour(0, 0, 0, 200),
- textColour: toColour(200, 200, 200, 255),
- textSize: 10.0,
- textFont: robotoFont,
- },
- backgroundColour: toColour(0, 0, 0, 200),
- textColour: toColour(200, 200, 200, 255),
- textSize: 10.0,
- textFont: robotoFont,
- },
- item: {
- hover: {
- backgroundColour: toColour(32, 32, 32, 200),
- textColour: toColour(200, 200, 200, 255),
- textSize: 10.0,
- textFont: robotoFont,
- width: 200,
- },
- backgroundColour: toColour(0, 0, 0, 200),
- textColour: toColour(200, 200, 200, 255),
- textSize: 10.0,
- textFont: robotoFont,
- width: 200,
- },
- focused: {
- borderColour: toColour(focusedColour[0], focusedColour[1], focusedColour[2], 255),
- },
- invalidValue: {
- borderColour: toColour(invalidValueColour[0], invalidValueColour[1], invalidValueColour[2], 255),
- },
- });
-
- for(let i in placesOfOrigin) {
- newCharacter.placeOfOrigin.item(placesOfOrigin[i]);
- }
-
- newCharacter.placeOfOrigin.axis.y.scrollBar.styles.innerBar.backgroundColour = toColour(primaryColour[0], primaryColour[1], primaryColour[2], buttonAlpha);
- newCharacter.placeOfOrigin.setScrollBarsManual(true);
-
- newCharacter.skinImage = newCharacter.window.image(250, 32, 110, 70, "files/images/skins/none.png", {
- focused: {
- borderColour: toColour(0, 0, 0, 0),
- },
- });
-
- newCharacter.skinDropDown = newCharacter.window.dropDown(220, 100, 200, 25, 'Choose Skin', {
- main: {
- hover: {
- backgroundColour: toColour(0, 0, 0, 200),
- textColour: toColour(200, 200, 200, 255),
- textSize: 10.0,
- textFont: robotoFont,
- },
backgroundColour: toColour(0, 0, 0, 120),
textColour: toColour(200, 200, 200, 255),
textSize: 10.0,
textFont: robotoFont,
- width: 200,
},
- item: {
- hover: {
- backgroundColour: toColour(primaryColour[0], primaryColour[1], primaryColour[2], 150),
- textColour: toColour(200, 200, 200, 255),
- textSize: 10.0,
- textFont: robotoFont,
- width: 200,
- },
- backgroundColour: toColour(0, 0, 0, 200),
- textColour: toColour(200, 200, 200, 255),
+ caret: {
+ lineColour: toColour(255, 255, 255, 255),
+ },
+ placeholder: {
+ backgroundColour: toColour(0, 0, 0, 120),
+ textColour: toColour(200, 200, 200, 200),
textSize: 10.0,
textFont: robotoFont,
- width: 200,
- },
+ }
});
+ newCharacter.firstNameInput.placeholder = "First Name";
- newCharacter.skinDropDown.axis.y.scrollBar.styles.innerBar.backgroundColour = toColour(primaryColour[0], primaryColour[1], primaryColour[2], buttonAlpha);
- newCharacter.skinDropDown.setScrollBarsManual(true);
+ newCharacter.lastNameInput = newCharacter.window.textInput(20, 130, 260, 25, '', {
+ main: {
+ backgroundColour: toColour(0, 0, 0, 120),
+ textColour: toColour(200, 200, 200, 255),
+ textSize: 10.0,
+ textFont: robotoFont,
+ },
+ caret: {
+ lineColour: toColour(255, 255, 255, 255),
+ },
+ placeholder: {
+ backgroundColour: toColour(0, 0, 0, 120),
+ textColour: toColour(150, 150, 150, 200),
+ textSize: 10.0,
+ textFont: robotoFont,
+ }
+ });
+ newCharacter.lastNameInput.placeholder = "Last Name";
- for(let i in skinNames[gta.game]) {
- newCharacter.skinDropDown.item(skinNames[gta.game][i][1]);
- }
-
- newCharacter.createButton = newCharacter.window.button(220, 130, 200, 25, 'CREATE', {
+ newCharacter.createCharacterButton = newCharacter.window.button(20, 160, 260, 25, 'CREATE CHARACTER', {
main: {
backgroundColour: toColour(primaryColour[0], primaryColour[1], primaryColour[2], buttonAlpha),
- textColour: toColour(0, 0, 0, 255),
- textSize: 10.0,
+ textColour: toColour(255, 255, 255, 255),
+ textSize: 12.0,
textFont: robotoFont,
textAlign: 0.5,
},
@@ -1444,7 +401,7 @@ app.init = function()
}, checkNewCharacter);
logToConsole(LOG_DEBUG, `[Asshat.GUI] Created new character GUI`);
- // ------------------------------------------------------------------------------
+ // ===========================================================================
logToConsole(LOG_DEBUG, `[Asshat.GUI] Creating register GUI ...`);
register.window = mexui.window(game.width/2-130, game.height/2-125, 300, 250, 'Register', {
@@ -1557,10 +514,10 @@ app.init = function()
}, checkRegistration);
logToConsole(LOG_DEBUG, `[Asshat.GUI] Created register GUI`);
- // ------------------------------------------------------------------------------
+ // ===========================================================================
logToConsole(LOG_DEBUG, `[Asshat.GUI] Creating error GUI ...`);
- errorDialog.window = mexui.window(game.width/2-200, game.height/2-70, 400, 140, 'ERROR', {
+ errorDialog.window = mexui.window(game.width/2-200, game.height/2-70, 500, 140, 'ERROR', {
main: {
backgroundColour: toColour(0, 0, 0, windowAlpha),
transitionTime: 500,
@@ -1577,13 +534,16 @@ app.init = function()
},
});
- errorDialog.messageLabel = errorDialog.window.text(15, 50, 370, 20, 'Error Message', {
+ errorDialog.messageLabel = errorDialog.window.text(15, 50, 470, 75, 'Error Message', {
main: {
textSize: 10.0,
textAlign: 0.5,
textColour: toColour(255, 255, 255, 255),
textFont: robotoFont,
- }
+ },
+ focused: {
+ borderColour: toColour(0, 0, 0, 0),
+ },
});
errorDialog.okayButton = errorDialog.window.button(20, 95, 360, 30, 'OK', {
@@ -1594,10 +554,13 @@ app.init = function()
textFont: robotoFont,
textAlign: 0.5,
},
+ focused: {
+ borderColour: toColour(primaryColour[0], primaryColour[1], primaryColour[2], 255),
+ },
}, closeErrorDialog);
logToConsole(LOG_DEBUG, `[Asshat.GUI] Created error GUI ...`);
- // ------------------------------------------------------------------------------
+ // ===========================================================================
logToConsole(LOG_DEBUG, `[Asshat.GUI] Created prompt GUI ...`);
yesNoDialog.window = mexui.window(game.width/2-200, game.height/2-70, 400, 140, 'Question', {
@@ -1623,7 +586,10 @@ app.init = function()
textAlign: 0.5,
textColour: toColour(255, 255, 255, 255),
textFont: robotoFont,
- }
+ },
+ focused: {
+ borderColour: toColour(0, 0, 0, 0),
+ },
});
yesNoDialog.yesButton = yesNoDialog.window.button(20, 95, 175, 30, 'YES', {
@@ -1634,6 +600,9 @@ app.init = function()
textFont: robotoFont,
textAlign: 0.5,
},
+ focused: {
+ borderColour: toColour(primaryColour[0], primaryColour[1], primaryColour[2], 255),
+ },
}, yesNoDialogAnswerYes);
yesNoDialog.noButton = yesNoDialog.window.button(205, 95, 175, 30, 'NO', {
@@ -1644,10 +613,13 @@ app.init = function()
textFont: robotoFont,
textAlign: 0.5,
},
+ focused: {
+ borderColour: toColour(primaryColour[0], primaryColour[1], primaryColour[2], 255),
+ },
}, yesNoDialogAnswerNo);
logToConsole(LOG_DEBUG, `[Asshat.GUI] Created prompt GUI`);
- // ------------------------------------------------------------------------------
+ // ===========================================================================
logToConsole(LOG_DEBUG, `[Asshat.GUI] Creating info dialog GUI ...`);
infoDialog.window = mexui.window(game.width/2-200, game.height/2-70, 400, 140, 'Information', {
@@ -1672,7 +644,10 @@ app.init = function()
textAlign: 0.5,
textColour: toColour(255, 255, 255, 220),
textFont: robotoFont,
- }
+ },
+ focused: {
+ borderColour: toColour(0, 0, 0, 0),
+ },
});
infoDialog.okayButton = infoDialog.window.button(20, 95, 360, 30, 'OK', {
@@ -1683,13 +658,74 @@ app.init = function()
textFont: robotoFont,
textAlign: 0.5,
},
+ focused: {
+ borderColour: toColour(primaryColour[0], primaryColour[1], primaryColour[2], 255),
+ },
}, closeInfoDialog);
logToConsole(LOG_DEBUG, `[Asshat.GUI] Created info dialog GUI`);
- // ------------------------------------------------------------------------------
+// ===========================================================================
+
+ logToConsole(LOG_DEBUG, `[Asshat.GUI] Creating list dialog GUI ...`);
+ listDialog.window = mexui.window(game.width/2-200, game.height/2-70, 400, 500, 'List', {
+ main: {
+ backgroundColour: toColour(0, 0, 0, windowAlpha),
+ },
+ title: {
+ textSize: 11.0,
+ textColour: toColour(0, 0, 0, 255),
+ backgroundColour: toColour(primaryColour[0], primaryColour[1], primaryColour[2], windowTitleAlpha),
+ },
+ icon: {
+ textSize: 11.0,
+ textColour: toColour(255, 255, 255, 255),
+ backgroundColour: toColour(primaryColour[0], primaryColour[1], primaryColour[2], windowTitleAlpha),
+ hover: {
+ backgroundColour: toColour(205, 60, 60, windowTitleAlpha),
+ },
+ },
+ });
+
+ listDialog.messageLabel = infoDialog.window.text(5, 5, 390, 20, 'Select one', {
+ main: {
+ textSize: 10.0,
+ textAlign: 0.5,
+ textColour: toColour(255, 255, 255, 220),
+ textFont: robotoFont,
+ },
+ focused: {
+ borderColour: toColour(0, 0, 0, 0),
+ },
+ });
+
+ listDialog.listGrid = listDialog.window.grid(5, 25, 390, 450, {
+ main: {
+ backgroundColour: toColour(0, 0, 0, windowAlpha),
+ },
+ column: {
+ lineColour: toColour(primaryColour[0], primaryColour[1], primaryColour[2], windowTitleAlpha),
+ },
+ header: {
+ backgroundColour: toColour(primaryColour[0], primaryColour[1], primaryColour[2], windowTitleAlpha-50),
+ textColour: toColour(primaryColour[0], primaryColour[1], primaryColour[2], windowTitleAlpha),
+ },
+ cell: {
+ backgroundColour: toColour(0, 0, 0, windowAlpha),
+ textColour: toColour(primaryColour[0], primaryColour[1], primaryColour[2], windowTitleAlpha),
+ },
+ row: {
+ lineColour: toColour(primaryColour[0], primaryColour[1], primaryColour[2], windowTitleAlpha),
+ hover: {
+ backgroundColour: toColour(primaryColour[0], primaryColour[1], primaryColour[2], 120),
+ }
+ }
+ });
+ logToConsole(LOG_DEBUG, `[Asshat.GUI] Created list dialog GUI`);
+
+ // ===========================================================================
logToConsole(LOG_DEBUG, `[Asshat.GUI] Creating character select GUI ...`);
- characterSelect.window = mexui.window(game.width/2-215, game.height/2-83, 430, 166, 'Select Character', {
+ characterSelect.window = mexui.window(game.width/2-215, game.height/2-83, 430, 190, 'Select Character', {
main: {
backgroundColour: toColour(0, 0, 0, windowAlpha),
},
@@ -1705,7 +741,7 @@ app.init = function()
}
});
- characterSelect.nameText = characterSelect.window.text(10, 40, 200, 25, 'Lastname, Firstname', {
+ characterSelect.nameText = characterSelect.window.text(5, 40, 200, 25, 'Lastname, Firstname', {
main: {
textSize: 14.0,
textAlign: 0.0,
@@ -1717,7 +753,7 @@ app.init = function()
}
});
- characterSelect.dateOfBirthText = characterSelect.window.text(10, 70, 200, 25, 'Born: ', {
+ characterSelect.cashText = characterSelect.window.text(5, 65, 200, 25, 'Cash: $0', {
main: {
textSize: 9.0,
textAlign: 0.0,
@@ -1729,7 +765,7 @@ app.init = function()
}
});
- characterSelect.placeOfOrigin = characterSelect.window.text(10, 90, 200, 25, 'From: ', {
+ characterSelect.clanText = characterSelect.window.text(5, 80, 200, 25, 'Clan: None', {
main: {
textSize: 9.0,
textAlign: 0.0,
@@ -1741,7 +777,19 @@ app.init = function()
}
});
- characterSelect.selectCharacterButton = characterSelect.window.button(90, 130, 250, 25, 'SELECT', {
+ characterSelect.lastPlayedText = characterSelect.window.text(5, 95, 200, 25, 'Last Played: Never', {
+ main: {
+ textSize: 9.0,
+ textAlign: 0.0,
+ textColour: toColour(255, 255, 255, 220),
+ textFont: robotoFont,
+ },
+ focused: {
+ borderColour: toColour(0, 0, 0, 0),
+ }
+ });
+
+ characterSelect.selectCharacterButton = characterSelect.window.button(85, 130, 260, 25, 'SELECT', {
main: {
backgroundColour: toColour(primaryColour[0], primaryColour[1], primaryColour[2], buttonAlpha),
textColour: toColour(0, 0, 0, 255),
@@ -1754,7 +802,7 @@ app.init = function()
}
}, selectThisCharacter);
- characterSelect.newCharacterButton = characterSelect.window.button(140, 180, 150, 25, 'NEW CHARACTER', {
+ characterSelect.newCharacterButton = characterSelect.window.button(5, 160, 420, 25, 'NEW CHARACTER', {
main: {
backgroundColour: toColour(primaryColour[0], primaryColour[1], primaryColour[2], buttonAlpha),
textColour: toColour(0, 0, 0, 255),
@@ -1767,7 +815,7 @@ app.init = function()
}
}, showNewCharacter);
- characterSelect.previousCharacterButton = characterSelect.window.button(10, 130, 75, 25, '< PREV', {
+ characterSelect.previousCharacterButton = characterSelect.window.button(5, 130, 75, 25, '< PREV', {
main: {
backgroundColour: toColour(primaryColour[0], primaryColour[1], primaryColour[2], buttonAlpha),
textColour: toColour(0, 0, 0, 255),
@@ -1780,7 +828,7 @@ app.init = function()
}
}, selectPreviousCharacter);
- characterSelect.nextCharacterButton = characterSelect.window.button(345, 130, 75, 25, 'NEXT >', {
+ characterSelect.nextCharacterButton = characterSelect.window.button(350, 130, 75, 25, 'NEXT >', {
main: {
backgroundColour: toColour(primaryColour[0], primaryColour[1], primaryColour[2], buttonAlpha),
textColour: toColour(0, 0, 0, 255),
@@ -1800,20 +848,20 @@ app.init = function()
});
logToConsole(LOG_DEBUG, `[Asshat.GUI] Created character select GUI`);
- // ---------------------------------------------------------------------------
+ // ===========================================================================
logToConsole(LOG_DEBUG, `[Asshat.GUI] All GUI created successfully!`);
closeAllWindows();
};
-// ---------------------------------------------------------------------------
+// ===========================================================================
let checkLogin = function() {
logToConsole(LOG_DEBUG, `[Asshat.GUI] Checking login with server ...`);
triggerNetworkEvent("ag.checkLogin", login.passwordInput.lines[0]);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
let loginFailed = function(errorMessage) {
logToConsole(LOG_DEBUG, `[Asshat.GUI] Server reports login failed`);
@@ -1822,21 +870,21 @@ let loginFailed = function(errorMessage) {
login.passwordInput.text = "";
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
let loginSuccess = function() {
logToConsole(LOG_DEBUG, `[Asshat.GUI] Server reports login was successful`);
closeAllWindows();
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
let checkRegistration = function() {
logToConsole(LOG_DEBUG, `[Asshat.GUI] Checking registration with server ...`);
triggerNetworkEvent("ag.checkRegistration", register.passwordInput.lines[0], register.confirmPasswordInput.lines[0], register.emailInput.lines[0]);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
let checkNewCharacter = function() {
logToConsole(LOG_DEBUG, `[Asshat.GUI] Checking new character with server ...`);
@@ -1850,24 +898,13 @@ let checkNewCharacter = function() {
return false;
}
- if(newCharacter.skinDropDown.selectedEntryIndex != -1) {
- skinId = skinNames[gta.game][newCharacter.skinDropDown.selectedEntryIndex][0];
- }
-
- if(newCharacter.placeOfOrigin.selectedEntryIndex == -1) {
- placeOfOrigin = 0;
- }
-
triggerNetworkEvent("ag.checkNewCharacter",
newCharacter.firstNameInput.lines[0],
newCharacter.lastNameInput.lines[0],
- toString(toString(newCharacter.dateOfBirth.day) + "/" + toString(newCharacter.dateOfBirth.month) + "/" + toString(newCharacter.dateOfBirth.year)),
- placesOfOrigin[newCharacter.placeOfOrigin.selectedEntryIndex],
- skinId,
);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
let registrationFailed = function(errorMessage) {
logToConsole(LOG_DEBUG, `[Asshat.GUI] Server reports registration failed. Reason: ${errorMessage}`);
@@ -1878,14 +915,24 @@ let registrationFailed = function(errorMessage) {
register.emailInput.text = "";
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
+
+let newCharacterFailed = function(errorMessage) {
+ logToConsole(LOG_DEBUG, `[Asshat.GUI] Server reports new character creation failed. Reason: ${errorMessage}`);
+ newCharacter.messageLabel.text = errorMessage;
+ newCharacter.messageLabel.styles.main.textColour = toColour(180, 32, 32, 255);
+ newCharacter.firstNameInput.text = "";
+ newCharacter.lastNameInput.text = "";
+}
+
+// ===========================================================================
let registrationSuccess = function() {
logToConsole(LOG_DEBUG, `[Asshat.GUI] Server reports registration was successful`);
closeAllWindows();
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
let twoFactorAuthFailed = function(errorMessage) {
logToConsole(LOG_DEBUG, `[Asshat.GUI] Server reports two-factor authentication failed. Reason: ${errorMessage}`);
@@ -1894,28 +941,28 @@ let twoFactorAuthFailed = function(errorMessage) {
login.passwordInput.text = "";
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
let twoFactorAuthSuccess = function() {
logToConsole(LOG_DEBUG, `[Asshat.GUI] Server reports two-factor authentication was successful`);
closeAllWindows();
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
let checkTwoFactorAuth = function() {
logToConsole(LOG_DEBUG, `[Asshat.GUI] Checking two-factor authentication with server ...`);
triggerNetworkEvent("ag.checkTwoFactorAuth", twoFactorAuth.codeInput.lines[0]);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
let characterSelectSuccess = function() {
logToConsole(LOG_DEBUG, `[Asshat.GUI] Server reports character selection was successful`);
closeAllWindows();
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
let closeErrorDialog = function() {
logToConsole(LOG_DEBUG, `[Asshat.GUI] Closing error dialog`);
@@ -1923,7 +970,7 @@ let closeErrorDialog = function() {
mexui.setInput(false);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
let closeInfoDialog = function() {
logToConsole(LOG_DEBUG, `[Asshat.GUI] Closing info dialog`);
@@ -1931,12 +978,11 @@ let closeInfoDialog = function() {
mexui.setInput(false);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
let closeAllWindows = function() {
logToConsole(LOG_DEBUG, `[Asshat.GUI] Closing all GUI windows`);
infoDialog.window.shown = false;
- errorDialog.window.shown = false;
yesNoDialog.window.shown = false;
errorDialog.window.shown = false;
register.window.shown = false;
@@ -1944,24 +990,27 @@ let closeAllWindows = function() {
newCharacter.window.shown = false;
characterSelect.window.shown = false;
twoFactorAuth.window.shown = false;
+ listDialog.window.shown = false;
mexui.setInput(false);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
let yesNoDialogAnswerNo = function() {
logToConsole(LOG_DEBUG, `[Asshat.GUI] Responding with answer NO to server prompt`);
triggerNetworkEvent("ag.promptAnswerNo");
+ closeAllWindows();
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
let yesNoDialogAnswerYes = function() {
logToConsole(LOG_DEBUG, `[Asshat.GUI] Responding with answer YES to server prompt`);
triggerNetworkEvent("ag.promptAnswerYes");
+ closeAllWindows();
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
let showRegistration = function() {
logToConsole(LOG_DEBUG, `[Asshat.GUI] Showing registration window`);
@@ -1971,7 +1020,7 @@ let showRegistration = function() {
register.window.shown = true;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
let showLogin = function() {
closeAllWindows();
@@ -1981,7 +1030,7 @@ let showLogin = function() {
login.window.shown = true;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
let showTwoFactorAuth = function() {
closeAllWindows();
@@ -1991,21 +1040,22 @@ let showTwoFactorAuth = function() {
twoFactorAuth.window.shown = true;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
-let showCharacterSelect = function(firstName, lastName, placeOfOrigin, dateOfBirth, skinId) {
+let showCharacterSelect = function(firstName, lastName, cash, clan, lastPlayed, skinId) {
closeAllWindows();
logToConsole(LOG_DEBUG, `[Asshat.GUI] Showing character selection window`);
setChatWindowEnabled(false);
mexui.setInput(true);
- characterSelect.nameText.text = lastName + ", " + firstName;
- characterSelect.dateOfBirthText.text = "Born: " + toString(dateOfBirth);
- characterSelect.placeOfOrigin.text = "From: " + toString(placeOfOrigin);
+ characterSelect.nameText.text = `${firstName} ${lastName}`;
+ characterSelect.cashText.text = `Money: $${cash}`;
+ characterSelect.clanText.text = `Clan: ${clan}`;
+ characterSelect.lastPlayedText.text = `Last Played: ${lastPlayed}`;
characterSelect.skinImage = characterSelect.window.image(310, 32, 100, 90, "files/images/skins/none.png");
characterSelect.window.shown = true;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
let showError = function(errorMessage, errorTitle) {
closeAllWindows();
@@ -2016,7 +1066,7 @@ let showError = function(errorMessage, errorTitle) {
errorDialog.window.shown = true;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
let showYesNo = function(promptMessage, promptTitle) {
closeAllWindows();
@@ -2026,7 +1076,7 @@ let showYesNo = function(promptMessage, promptTitle) {
yesNoDialog.window.shown = true;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
let showInfo = function(infoMessage, infoTitle) {
closeAllWindows();
@@ -2036,114 +1086,121 @@ let showInfo = function(infoMessage, infoTitle) {
infoDialog.window.shown = true;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
let showNewCharacter = function() {
closeAllWindows();
- logToConsole(LOG_DEBUG, `[Asshat.GUI] Showing info dialog window`);
+ logToConsole(LOG_DEBUG, `[Asshat.GUI] Showing new character dialog window`);
setChatWindowEnabled(false);
mexui.setInput(true);
+ setHUDEnabled(false);
newCharacter.window.shown = true;
+
+ //gui.showCursor(true, false);
+ //localPlayer.invincible = true;
+ //localPlayer.setProofs(true, true, true, true, true);
+ //localPlayer.collisionsEnabled = false;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
let selectNextCharacter = function() {
logToConsole(LOG_DEBUG, `[Asshat.GUI] Requesting next character info from server for character select window`);
triggerNetworkEvent("ag.nextCharacter");
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
let selectPreviousCharacter = function() {
logToConsole(LOG_DEBUG, `[Asshat.GUI] Requesting previous character info from server for character select window`);
triggerNetworkEvent("ag.previousCharacter");
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
let selectThisCharacter = function() {
logToConsole(LOG_DEBUG, `[Asshat.GUI] Tell server the current shown character was selected in character select window`);
triggerNetworkEvent("ag.selectCharacter");
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
-let switchCharacterSelect = function(firstName, lastName, placeOfOrigin, dateOfBirth, skinId) {
+let switchCharacterSelect = function(firstName, lastName, cash, clan, lastPlayed, skinId) {
logToConsole(LOG_DEBUG, `[Asshat.GUI] Updating character info with data from server`);
setChatWindowEnabled(false);
characterSelect.window.shown = false;
- characterSelect.nameText.text = lastName + ", " + firstName;
- characterSelect.dateOfBirthText.text = "Born: " + toString(dateOfBirth);
- characterSelect.placeOfOrigin.text = "From: " + toString(placeOfOrigin);
+ characterSelect.nameText.text = `${firstName} ${lastName}`;
+ characterSelect.cashText.text = `Money: $${cash}`;
+ characterSelect.clanText.text = `Clan: ${clan}`;
+ characterSelect.lastPlayedText.text = `Last Played: ${lastPlayed}`;
characterSelect.skinImage = characterSelect.window.image(310, 32, 100, 90, "files/images/skins/none.png");
characterSelect.window.shown = true;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
addNetworkHandler("ag.showLogin", function() {
logToConsole(LOG_DEBUG, `[Asshat.GUI] Received request from server to show login window`);
showLogin();
});
-// ---------------------------------------------------------------------------
+// ===========================================================================
addNetworkHandler("ag.showRegistration", function() {
logToConsole(LOG_DEBUG, `[Asshat.GUI] Received request from server to show registration window`);
showRegistration();
});
-// ---------------------------------------------------------------------------
+// ===========================================================================
addNetworkHandler("ag.showNewCharacter", function() {
logToConsole(LOG_DEBUG, `[Asshat.GUI] Received request from server to show new character window`);
showNewCharacter();
});
-// ---------------------------------------------------------------------------
+// ===========================================================================
-addNetworkHandler("ag.showCharacterSelect", function(firstName, lastName, placeOfOrigin, dateOfBirth, skinId) {
+addNetworkHandler("ag.showCharacterSelect", function(firstName, lastName, cash, clan, lastPlayed, skinId) {
logToConsole(LOG_DEBUG, `[Asshat.GUI] Received request from server to show character selection window`);
- showCharacterSelect(firstName, lastName, placeOfOrigin, dateOfBirth, skinId);
+ showCharacterSelect(firstName, lastName, cash, clan, lastPlayed, skinId);
});
-// ---------------------------------------------------------------------------
+// ===========================================================================
-addNetworkHandler("ag.switchCharacterSelect", function(firstName, lastName, placeOfOrigin, dateOfBirth, skinId) {
+addNetworkHandler("ag.switchCharacterSelect", function(firstName, lastName, cash, clan, lastPlayed, skinId) {
logToConsole(LOG_DEBUG, `[Asshat.GUI] Received request from server to update character selection window with new info`);
- switchCharacterSelect(firstName, lastName, placeOfOrigin, dateOfBirth, skinId);
+ switchCharacterSelect(firstName, lastName, cash, clan, lastPlayed, skinId);
});
-// ---------------------------------------------------------------------------
+// ===========================================================================
addNetworkHandler("ag.showError", function(errorMessage, errorTitle) {
logToConsole(LOG_DEBUG, `[Asshat.GUI] Received request from server to show error window`);
showError(errorMessage, errorTitle);
});
-// ---------------------------------------------------------------------------
+// ===========================================================================
addNetworkHandler("ag.showPrompt", function(promptMessage, promptTitle) {
logToConsole(LOG_DEBUG, `[Asshat.GUI] Received request from server to show prompt window`);
showYesNo(promptMessage, promptTitle);
});
-// ---------------------------------------------------------------------------
+// ===========================================================================
addNetworkHandler("ag.showInfo", function(infoMessage) {
logToConsole(LOG_DEBUG, `[Asshat.GUI] Received request from server to show info dialog`);
showInfo(infoMessage);
});
-// ---------------------------------------------------------------------------
+// ===========================================================================
addNetworkHandler("ag.loginSuccess", function() {
logToConsole(LOG_DEBUG, `[Asshat.GUI] Received signal of successful login from server`);
loginSuccess();
});
-// ---------------------------------------------------------------------------
+// ===========================================================================
addNetworkHandler("ag.characterSelectSuccess", function() {
logToConsole(LOG_DEBUG, `[Asshat.GUI] Received signal of successful character selection from server`);
@@ -2151,28 +1208,35 @@ addNetworkHandler("ag.characterSelectSuccess", function() {
setChatWindowEnabled(true);
});
-// ---------------------------------------------------------------------------
+// ===========================================================================
addNetworkHandler("ag.loginFailed", function(remainingAttempts) {
logToConsole(LOG_DEBUG, `[Asshat.GUI] Received signal of failed login from server`);
loginFailed(remainingAttempts);
});
-// ---------------------------------------------------------------------------
+// ===========================================================================
addNetworkHandler("ag.registrationSuccess", function() {
logToConsole(LOG_DEBUG, `[Asshat.GUI] Received signal of successful registration from server`);
registrationSuccess();
});
-// ---------------------------------------------------------------------------
+// ===========================================================================
addNetworkHandler("ag.registrationFailed", function(errorMessage) {
logToConsole(LOG_DEBUG, `[Asshat.GUI] Received signal of failed registration from server`);
registrationFailed(errorMessage);
});
-// ---------------------------------------------------------------------------
+// ===========================================================================
+
+addNetworkHandler("ag.newCharacterFailed", function(errorMessage) {
+ logToConsole(LOG_DEBUG, `[Asshat.GUI] Received signal of failed registration from server`);
+ newCharacterFailed(errorMessage);
+});
+
+// ===========================================================================
addNetworkHandler("ag.guiColour", function(red, green, blue) {
logToConsole(LOG_DEBUG, `[Asshat.GUI] Received new GUI colours from server`);
@@ -2180,12 +1244,12 @@ addNetworkHandler("ag.guiColour", function(red, green, blue) {
focusedColour = [red+focusedColourOffset, green+focusedColourOffset, blue+focusedColourOffset];
});
-// ---------------------------------------------------------------------------
+// ===========================================================================
addNetworkHandler("ag.guiInit", function() {
logToConsole(LOG_DEBUG, `[Asshat.GUI] Initializing MexUI app`);
- app.init();
+ initGUI();
triggerNetworkEvent("ag.guiReady", true);
});
-// ---------------------------------------------------------------------------
\ No newline at end of file
+// ===========================================================================
\ No newline at end of file
diff --git a/scripts/client/item.js b/scripts/client/item.js
new file mode 100644
index 00000000..0b4293fd
--- /dev/null
+++ b/scripts/client/item.js
@@ -0,0 +1,63 @@
+// ===========================================================================
+// Asshat-Gaming Roleplay
+// https://github.com/VortrexFTW/gtac_asshat_rp
+// Copyright (c) 2021 Asshat-Gaming (https://asshatgaming.com)
+// ===========================================================================
+// FILE: item.js
+// DESC: Provides item action and hotbar functions
+// TYPE: Client (JavaScript)
+// ===========================================================================
+
+let itemActionDelayDuration = 0;
+let itemActionDelayStart = 0;
+let itemActionDelayEnabled = false;
+let itemActionDelayPosition = toVector2(gta.width/2-100, gta.height-10);
+let itemActionDelaySize = toVector2(200, 5);
+
+// ===========================================================================
+
+function initItemScript() {
+ logToConsole(LOG_DEBUG, "[Asshat.Item]: Initializing item script ...");
+ logToConsole(LOG_DEBUG, "[Asshat.Item]: Item script initialized!");
+}
+
+// ===========================================================================
+
+function processItemActionRendering() {
+ if(renderItemActionDelay) {
+ if(itemActionDelayEnabled) {
+ let finishTime = itemActionDelayStart+itemActionDelayDuration;
+ if(sdl.ticks >= finishTime) {
+ itemActionDelayEnabled = false;
+ itemActionDelayDuration = 0;
+ itemActionDelayStart = 0;
+ tellServerItemActionDelayComplete();
+ } else {
+ let currentTick = sdl.ticks-itemActionDelayStart;
+ let progressPercent = Math.ceil(currentTick*100/itemActionDelayDuration);
+ let width = Math.ceil(getPercentage(itemActionDelaySize.x, progressPercent));
+
+ let backgroundColour = toColour(0, 0, 0, 255);
+ graphics.drawRectangle(null, [itemActionDelayPosition.x-(itemActionDelaySize.x/2)-1, itemActionDelayPosition.y-(itemActionDelaySize.y/2)-1], [itemActionDelaySize.x+2, itemActionDelaySize.y+2], backgroundColour, backgroundColour, backgroundColour, backgroundColour);
+ graphics.drawRectangle(null, [itemActionDelayPosition.x-(itemActionDelaySize.x/2), itemActionDelayPosition.y-(itemActionDelaySize.y/2)-2], [width, itemActionDelaySize.y], COLOUR_LIME, COLOUR_LIME, COLOUR_LIME, COLOUR_LIME);
+ }
+ }
+ }
+}
+
+// ===========================================================================
+
+function updatePlayerHotBar(activeSlot, itemsArray) {
+ logToConsole(LOG_DEBUG, `[Asshat.Main] Updating hotbar`);
+}
+
+// ===========================================================================
+
+function showItemActionDelay(duration) {
+ itemActionDelayDuration = duration;
+ itemActionDelayStart = sdl.ticks;
+ itemActionDelayEnabled = true;
+ logToConsole(LOG_DEBUG, `Item action delay started. Duration: ${itemActionDelayDuration}, Start: ${itemActionDelayStart}, Rendering Enabled: ${renderItemActionDelay}`);
+}
+
+// ===========================================================================
\ No newline at end of file
diff --git a/scripts/client/job.js b/scripts/client/job.js
new file mode 100644
index 00000000..93fca0e9
--- /dev/null
+++ b/scripts/client/job.js
@@ -0,0 +1,76 @@
+// ===========================================================================
+// Asshat-Gaming Roleplay
+// https://github.com/VortrexFTW/gtac_asshat_rp
+// Copyright (c) 2021 Asshat-Gaming (https://asshatgaming.com)
+// ===========================================================================
+// FILE: job.js
+// DESC: Provides job functions and usage
+// TYPE: Client (JavaScript)
+// ===========================================================================
+
+let localPlayerJobType = 0;
+let localPlayerWorking = false;
+let jobRouteStopBlip = null;
+let jobRouteStopSphere = null;
+
+// ===========================================================================
+
+function initJobScript() {
+ logToConsole(LOG_DEBUG, "[Asshat.Job]: Initializing job script ...");
+ logToConsole(LOG_DEBUG, "[Asshat.Job]: Job script initialized!");
+}
+
+// ===========================================================================
+
+function setLocalPlayerJobType(tempJobType) {
+ logToConsole(LOG_DEBUG, `[Asshat.Main] Set local player job type to ${tempJobType}`);
+ localPlayerJobType = tempJobType;
+}
+
+// ===========================================================================
+
+function setLocalPlayerWorkingState(tempWorking) {
+ logToConsole(LOG_DEBUG, `[Asshat.Main] Setting working state to ${tempWorking}`);
+ localPlayerWorking = tempWorking;
+}
+
+// ===========================================================================
+
+function showJobRouteStop() {
+ logToConsole(LOG_DEBUG, `[Asshat.Job] Showing route stop`);
+ if(gta.game == GAME_GTA_SA) {
+ jobRouteStopSphere = gta.createPickup(1318, position, 1);
+ } else {
+ jobRouteStopSphere = gta.createSphere(position, 3);
+ jobRouteStopSphere.colour = colour;
+ }
+
+ jobRouteStopBlip = gta.createBlip(position, 0, 2, colour);
+}
+
+// ===========================================================================
+
+function showJobRouteStop(position, colour) {
+ logToConsole(LOG_DEBUG, `[Asshat.Job] Showing route stop`);
+ if(gta.game == GAME_GTA_SA) {
+ jobRouteStopSphere = gta.createPickup(1318, position, 1);
+ } else {
+ jobRouteStopSphere = gta.createSphere(position, 3);
+ jobRouteStopSphere.colour = colour;
+ }
+
+ jobRouteStopBlip = gta.createBlip(position, 0, 2, colour);
+}
+
+// ===========================================================================
+
+function enteredJobRouteSphere() {
+ logToConsole(LOG_DEBUG, `[Asshat.Job] Entered job route sphere`);
+ tellServerPlayerArrivedAtJobRouteStop();
+ destroyElement(jobRouteStopSphere);
+ destroyElement(jobRouteStopBlip);
+ jobRouteStopSphere = null;
+ jobRouteStopBlip = null;
+}
+
+// ===========================================================================
\ No newline at end of file
diff --git a/scripts/client/keybind.js b/scripts/client/keybind.js
index d3c7490c..0e2a214f 100644
--- a/scripts/client/keybind.js
+++ b/scripts/client/keybind.js
@@ -1,8 +1,8 @@
// ===========================================================================
// Asshat-Gaming Roleplay
// https://github.com/VortrexFTW/gtac_asshat_rp
-// Copyright (c) 2020 Asshat-Gaming (https://asshatgaming.com)
-// ---------------------------------------------------------------------------
+// Copyright (c) 2021 Asshat-Gaming (https://asshatgaming.com)
+// ===========================================================================
// FILE: keybind.js
// DESC: Provides keybind features
// TYPE: Client (JavaScript)
@@ -10,29 +10,44 @@
let lastKeyBindUse = 0;
let keyBindDelayTime = 500;
+let keyBindShortHoldDuration = 500;
+let keyBindLongHoldDuration = 1500;
-// -------------------------------------------------------------------------
+// ===========================================================================
+
+function initKeyBindScript() {
+ logToConsole(LOG_DEBUG, "[Asshat.KeyBind]: Initializing key bind script ...");
+ logToConsole(LOG_DEBUG, "[Asshat.KeyBind]: Key bind script initialized!");
+}
+
+// ===========================================================================
function bindAccountKey(key, keyState) {
+ logToConsole(LOG_DEBUG, `[Asshat.KeyBind]: Binded key ${sdl.getKeyName(key)} (${key})`);
bindKey(toInteger(key), keyState, function(event) {
if(hasKeyBindDelayElapsed()) {
- lastKeyBindUse = sdl.ticks;
- triggerNetworkEvent("ag.useKeyBind", key);
+ if(canLocalPlayerUseKeyBinds()) {
+ logToConsole(LOG_DEBUG, `[Asshat.KeyBind]: Using keybind for key ${sdl.getKeyName(key)} (${key})`);
+ lastKeyBindUse = sdl.ticks;
+ tellServerPlayerUsedKeyBind(key);
+ } else {
+ logToConsole(LOG_ERROR, `[Asshat.KeyBind]: Failed to use keybind for key ${sdl.getKeyName(key)} (${key}) - Not allowed to use keybinds!`);
+ }
+ } else {
+ logToConsole(LOG_ERROR, `[Asshat.KeyBind]: Failed to use keybind for key ${sdl.getKeyName(key)} (${key}) - Not enough time has passed since last keybind use!`);
}
});
- return false;
}
-addNetworkHandler("ag.addKeyBind", bindAccountKey);
-// -------------------------------------------------------------------------
+// ===========================================================================
function unBindAccountKey(key) {
+ logToConsole(LOG_DEBUG, `[Asshat.KeyBind]: Unbinded key ${sdl.getKeyName(key)} (${key})`);
unbindKey(key);
return true;
}
-addNetworkHandler("ag.delKeyBind", unBindAccountKey);
-// -------------------------------------------------------------------------
+// ===========================================================================
function hasKeyBindDelayElapsed() {
if(sdl.ticks-lastKeyBindUse >= keyBindDelayTime) {
@@ -42,4 +57,10 @@ function hasKeyBindDelayElapsed() {
return false;
}
-// -------------------------------------------------------------------------
\ No newline at end of file
+// ===========================================================================
+
+function canLocalPlayerUseKeyBinds() {
+ return true; //(!usingSkinSelector && isSpawned && !itemActionDelayEnabled);
+}
+
+// ===========================================================================
\ No newline at end of file
diff --git a/scripts/client/label.js b/scripts/client/label.js
index 410760f5..242e2e35 100644
--- a/scripts/client/label.js
+++ b/scripts/client/label.js
@@ -1,8 +1,8 @@
// ===========================================================================
// Asshat-Gaming Roleplay
// https://github.com/VortrexFTW/gtac_asshat_rp
-// Copyright (c) 2020 Asshat-Gaming (https://asshatgaming.com)
-// ---------------------------------------------------------------------------
+// Copyright (c) 2021 Asshat-Gaming (https://asshatgaming.com)
+// ===========================================================================
// FILE: labels.js
// DESC: Provides functionality for world labels (3D labels)
// TYPE: Client (JavaScript)
@@ -25,19 +25,49 @@ let unlockedColour = toColour(50, 205, 50, 255);
let lockedColour = toColour(205, 92, 92, 255);
let jobHelpColour = toColour(234, 198, 126, 255);
-// -------------------------------------------------------------------------
+let renderLabelDistance = 7.5;
-bindEventHandler("onResourceReady", thisResource, function(event, resource) {
- propertyLabelNameFont = lucasFont.createDefaultFont(16.0, "Roboto", "Regular");
- propertyLabelLockedFont = lucasFont.createDefaultFont(12.0, "Roboto", "Light");
+let propertyLabelLockedOffset = 16;
+let propertyLabelNameOffset = 18;
- jobNameLabelFont = lucasFont.createDefaultFont(16.0, "Roboto", "Regular");
- jobHelpLabelFont = lucasFont.createDefaultFont(10.0, "Roboto", "Light");
-});
+// ===========================================================================
-// -------------------------------------------------------------------------
+function initLabelScript() {
+ logToConsole(LOG_DEBUG, "[Asshat.Label]: Initializing label script ...");
+ propertyLabelNameFont = initLabelPropertyNameFont();
+ propertyLabelLockedFont = initLabelPropertyLockedFont();
+ jobNameLabelFont = initLabelJobNameFont();
+ jobHelpLabelFont = initLabelJobHelpFont();
+ logToConsole(LOG_DEBUG, "[Asshat.Label]: Label script initialized!");
+}
-function renderPropertyEntranceLabel(name, position, locked, isBusiness, price) {
+// ===========================================================================
+
+function initLabelPropertyNameFont() {
+ return lucasFont.createDefaultFont(16.0, "Roboto", "Regular");
+}
+
+// ===========================================================================
+
+function initLabelPropertyLockedFont() {
+ return lucasFont.createDefaultFont(12.0, "Roboto", "Light");
+}
+
+// ===========================================================================
+
+function initLabelJobNameFont() {
+ return lucasFont.createDefaultFont(16.0, "Roboto", "Regular");
+}
+
+// ===========================================================================
+
+function initLabelJobHelpFont() {
+ return lucasFont.createDefaultFont(10.0, "Roboto", "Light");
+}
+
+// ===========================================================================
+
+function renderPropertyEntranceLabel(name, position, locked, isBusiness, price, shouldShowBuyInfo) {
if(localPlayer == null) {
return false;
}
@@ -54,24 +84,35 @@ function renderPropertyEntranceLabel(name, position, locked, isBusiness, price)
tempPosition.z = tempPosition.z + propertyLabelHeight;
let screenPosition = getScreenFromWorldPosition(tempPosition);
+ if(screenPosition.x < 0 || screenPosition.x > gta.width) {
+ return false;
+ }
+
let text = "";
if(price > 0) {
text = `For sale: $${price}`;
let size = propertyLabelLockedFont.measure(text, game.width, 0.0, 0.0, propertyLabelLockedFont.size, true, true);
- propertyLabelLockedFont.render(text, [screenPosition.x-size[0]/2, screenPosition.y-size[1]/2], game.width, 0.0, 0.0, propertyLabelLockedFont.size, toColour(0, 150, 0, 255), false, true, false, true);
+ propertyLabelLockedFont.render(text, [screenPosition.x-size[0]/2, screenPosition.y-size[1]/2], game.width, 0.0, 0.0, propertyLabelLockedFont.size, toColour(200, 200, 200, 255), false, true, false, true);
- screenPosition.y -= 18;
+ screenPosition.y -= propertyLabelLockedOffset;
}
text = (locked) ? "LOCKED" : "UNLOCKED";
if(isBusiness) {
text = (locked) ? "CLOSED" : "OPEN";
+ if(!locked && shouldShowBuyInfo) {
+ if(getDistance(localPlayer.position, position) <= renderLabelDistance-2) {
+ let size = propertyLabelLockedFont.measure(`Use /buy to purchase items`, game.width, 0.0, 0.0, propertyLabelLockedFont.size, true, true);
+ propertyLabelLockedFont.render(`Use /buy to purchase items`, [screenPosition.x-size[0]/2, screenPosition.y-size[1]/2], game.width, 0.0, 0.0, propertyLabelLockedFont.size, toColour(234, 198, 126, 255), false, true, false, true);
+ screenPosition.y -= propertyLabelLockedOffset;
+ }
+ }
}
let size = propertyLabelLockedFont.measure(text, game.width, 0.0, 0.0, propertyLabelLockedFont.size, true, true);
propertyLabelLockedFont.render(text, [screenPosition.x-size[0]/2, screenPosition.y-size[1]/2], game.width, 0.0, 0.0, propertyLabelLockedFont.size, (locked) ? lockedColour : unlockedColour, false, true, false, true);
- screenPosition.y -= 22;
+ screenPosition.y -= propertyLabelNameOffset;
text = name || " ";
size = propertyLabelNameFont.measure(text, game.width, 0.0, 0.0, propertyLabelNameFont.size, true, true);
@@ -97,6 +138,10 @@ function renderPropertyExitLabel(position) {
tempPosition.z = tempPosition.z + propertyLabelHeight;
let screenPosition = getScreenFromWorldPosition(tempPosition);
+ if(screenPosition.x < 0 || screenPosition.x > gta.width) {
+ return false;
+ }
+
let text = "EXIT";
size = propertyLabelNameFont.measure(text, game.width, 0.0, 0.0, propertyLabelNameFont.size, true, true);
propertyLabelNameFont.render(text, [screenPosition.x-size[0]/2, screenPosition.y-size[1]/2], game.width, 0.0, 0.0, propertyLabelNameFont.size, COLOUR_WHITE, false, true, false, true);
@@ -121,6 +166,10 @@ function renderJobLabel(name, position, jobType) {
tempPosition.z = tempPosition.z + propertyLabelHeight;
let screenPosition = getScreenFromWorldPosition(tempPosition);
+ if(screenPosition.x < 0 || screenPosition.x > gta.width) {
+ return false;
+ }
+
let text = "";
if(jobType == localPlayerJobType) {
if(localPlayerWorking) {
@@ -149,32 +198,39 @@ function renderJobLabel(name, position, jobType) {
// -------------------------------------------------------------------------
function processLabelRendering() {
- if(localPlayer != null) {
- let pickups = getElementsByType(ELEMENT_PICKUP);
- for(let i in pickups) {
- if(pickups[i].getData("ag.label.type") != null) {
- if(getDistance(localPlayer.position, pickups[i].position) <= 7.5) {
- let price = 0;
- if(pickups[i].getData("ag.label.price") != null) {
- price = pickups[i].getData("ag.label.price");
- }
+ if(renderLabels && gta.game != GAME_GTA_IV) {
+ if(localPlayer != null) {
+ let pickups = getElementsByType(ELEMENT_PICKUP);
+ for(let i in pickups) {
+ if(pickups[i].getData("ag.label.type") != null) {
+ if(getDistance(localPlayer.position, pickups[i].position) <= renderLabelDistance) {
+ let price = 0;
+ let shouldShowBuyHelp = false;
+ if(pickups[i].getData("ag.label.price") != null) {
+ price = pickups[i].getData("ag.label.price");
+ }
- switch(pickups[i].getData("ag.label.type")) {
- case AG_LABEL_BUSINESS:
- renderPropertyEntranceLabel(pickups[i].getData("ag.label.name"), pickups[i].position, pickups[i].getData("ag.label.locked"), true, price);
- break;
+ if(pickups[i].getData("ag.label.buyhelp") != null) {
+ shouldShowBuyHelp = pickups[i].getData("ag.label.buyhelp");
+ }
- case AG_LABEL_HOUSE:
- renderPropertyEntranceLabel(pickups[i].getData("ag.label.name"), pickups[i].position, pickups[i].getData("ag.label.locked"), false, price);
- break;
+ switch(pickups[i].getData("ag.label.type")) {
+ case AG_LABEL_BUSINESS:
+ renderPropertyEntranceLabel(pickups[i].getData("ag.label.name"), pickups[i].position, pickups[i].getData("ag.label.locked"), true, price, shouldShowBuyHelp);
+ break;
- case AG_LABEL_JOB:
- renderJobLabel(pickups[i].getData("ag.label.name"), pickups[i].position, pickups[i].getData("ag.label.jobType"));
- break;
+ case AG_LABEL_HOUSE:
+ renderPropertyEntranceLabel(pickups[i].getData("ag.label.name"), pickups[i].position, pickups[i].getData("ag.label.locked"), false, price);
+ break;
- case AG_LABEL_EXIT:
- renderPropertyExitLabel(pickups[i].position);
- break;
+ case AG_LABEL_JOB:
+ renderJobLabel(pickups[i].getData("ag.label.name"), pickups[i].position, pickups[i].getData("ag.label.jobType"));
+ break;
+
+ case AG_LABEL_EXIT:
+ renderPropertyExitLabel(pickups[i].position);
+ break;
+ }
}
}
}
diff --git a/scripts/client/logo.js b/scripts/client/logo.js
new file mode 100644
index 00000000..f35b5522
--- /dev/null
+++ b/scripts/client/logo.js
@@ -0,0 +1,53 @@
+// ===========================================================================
+// Asshat-Gaming Roleplay
+// https://github.com/VortrexFTW/gtac_asshat_rp
+// Copyright (c) 2021 Asshat-Gaming (https://asshatgaming.com)
+// ===========================================================================
+// FILE: logo.js
+// DESC: Provides logo rendering functions
+// TYPE: Client (JavaScript)
+// ===========================================================================
+
+let logoImage = null;
+let logoPos = toVector2(gta.width-132, gta.height-132);
+let logoSize = toVector2(128, 128);
+
+// ===========================================================================
+
+function initLogoScript() {
+ logToConsole(LOG_DEBUG, "[Asshat.Logo]: Initializing logo script ...");
+ logoImage = loadLogoImage();
+ logToConsole(LOG_DEBUG, "[Asshat.Logo]: Logo script initialized!");
+}
+
+// ===========================================================================
+
+function loadLogoImage() {
+ let logoStream = openFile(mainLogoPath);
+ let tempLogoImage = null;
+ if(logoStream != null) {
+ tempLogoImage = drawing.loadPNG(logoStream);
+ logoStream.close();
+ }
+
+ return tempLogoImage;
+}
+
+// ===========================================================================
+
+function processLogoRendering() {
+ if(renderLogo) {
+ if(logoImage != null) {
+ graphics.drawRectangle(logoImage, logoPos, logoSize);
+ }
+ }
+}
+
+// ===========================================================================
+
+function setServerLogoRenderState(state) {
+ logToConsole(LOG_DEBUG, `[Asshat.Main] Server logo ${(state) ? "enabled" : "disabled"}`);
+ renderLogo = state;
+}
+
+// ===========================================================================
\ No newline at end of file
diff --git a/scripts/client/main.js b/scripts/client/main.js
index 3099ca1a..306bd4ae 100644
--- a/scripts/client/main.js
+++ b/scripts/client/main.js
@@ -1,40 +1,19 @@
// ===========================================================================
// Asshat-Gaming Roleplay
// https://github.com/VortrexFTW/gtac_asshat_rp
-// Copyright (c) 2020 Asshat-Gaming (https://asshatgaming.com)
-// ---------------------------------------------------------------------------
+// Copyright (c) 2021 Asshat-Gaming (https://asshatgaming.com)
+// ===========================================================================
// FILE: main.js
// DESC: Main client script (will be reorganized into individual files later)
// TYPE: Client (JavaScript)
// ===========================================================================
-// ---------------------------------------------------------------------------
-
-let bigMessageFont = null;
-let logoImage = null;
-
-let logoPos = toVector2(gta.width-132, gta.height-132);
-let logoSize = toVector2(128, 128);
-
-let jobRouteStopBlip = null;
-let jobRouteStopSphere = null;
-
-let smallGameMessageFont = null;
-let smallGameMessageText = "";
-let smallGameMessageColour = COLOUR_WHITE;
-let smallGameMessageTimer = null;
-
let inSphere = false;
let inVehicle = false;
let inVehicleSeat = false;
let isWalking = false;
let isSpawned = false;
-let localPlayerJobType = 0;
-let localPlayerWorking = false;
-
-let mouseCameraEnabled = false;
-
let garbageCollectorInterval = null;
let parkedVehiclePosition = false;
@@ -44,7 +23,7 @@ let renderHUD = true;
let renderLabels = true;
let renderLogo = true;
let renderSmallGameMessage = true;
-let renderScoreboard = true;
+let renderScoreBoard = true;
let renderHotBar = true;
let renderItemActionDelay = true;
@@ -57,729 +36,11 @@ let forceWeapon = 0;
let forceWeaponAmmo = 0;
let forceWeaponClipAmmo = 0;
-let itemActionDelayDuration = 0;
-let itemActionDelayStart = 0;
-let itemActionDelayEnabled = false;
-let itemActionDelayPosition = toVector2(gta.width/2, gta.height-100);
-let itemActionDelaySize = toVector2(100, 10);
-
let drunkEffectAmount = 0;
let drunkEffectDurationTimer = null;
-// ---------------------------------------------------------------------------
+let controlsEnabled = true;
-addEvent("OnLocalPlayerEnterSphere", 1);
-addEvent("OnLocalPlayerExitSphere", 1);
-addEvent("OnLocalPlayerEnteredVehicle", 1);
-addEvent("OnLocalPlayerExitedVehicle", 1);
-addEvent("OnLocalPlayerSwitchWeapon", 2);
+let streamingRadio = null;
-// ---------------------------------------------------------------------------
-
-bindEventHandler("onResourceReady", thisResource, function(event, resource) {
- if(resource == thisResource) {
- let fontStream = openFile("files/fonts/pricedown.ttf");
- if(fontStream != null) {
- bigMessageFont = lucasFont.createFont(fontStream, 28.0);
- smallGameMessageFont = lucasFont.createFont(fontStream, 20.0);
- fontStream.close();
- }
-
- let logoStream = openFile(mainLogoPath);
- if(logoStream != null) {
- logoImage = drawing.loadPNG(logoStream);
- logoStream.close();
- }
- }
-
- triggerNetworkEvent("ag.clientReady");
-
- openAllGarages();
-});
-
-// ---------------------------------------------------------------------------
-
-bindEventHandler("onResourceStart", thisResource, function(event, resource) {
- if(gta.game == GAME_GTA_SA) {
- gta.setDefaultInteriors(false);
- gta.setCiviliansEnabled(false);
- }
- garbageCollectorInterval = setInterval(collectAllGarbage, 1000*60);
- addNetworkHandler("ag.passenger", enterVehicleAsPassenger);
-
- triggerNetworkEvent("ag.clientStarted");
-});
-
-// ---------------------------------------------------------------------------
-
-addNetworkHandler("ag.connectCamera", function(cameraPosition, cameraLookat) {
- gta.fadeCamera(true);
- gta.setCameraLookAt(cameraPosition, cameraLookat, true);
-});
-
-// ---------------------------------------------------------------------------
-
-addNetworkHandler("ag.restoreCamera", function() {
- logToConsole(LOG_DEBUG, `[Asshat.Main] Camera restored`);
- gta.restoreCamera(true);
-});
-
-// ---------------------------------------------------------------------------
-
-addNetworkHandler("ag.clearPeds", function() {
- logToConsole(LOG_DEBUG, `[Asshat.Main] Clearing all self-owned peds ...`);
- clearSelfOwnedPeds();
- logToConsole(LOG_DEBUG, `[Asshat.Main] All self-owned peds cleared`);
-});
-
-// ---------------------------------------------------------------------------
-
-addNetworkHandler("ag.logo", function(state) {
- logToConsole(LOG_DEBUG, `[Asshat.Main] Server logo ${(state) ? "enabled" : "disabled"}`);
- renderLogo = state;
-});
-
-// ---------------------------------------------------------------------------
-
-addNetworkHandler("ag.ambience", function(state) {
- logToConsole(LOG_DEBUG, `[Asshat.Main] Ambient civilians and traffic ${(state) ? "enabled" : "disabled"}`);
- gta.setTrafficEnabled(state);
- gta.setGenerateCarsAroundCamera(state);
- if(gta.game != GAME_GTA_SA) {
- gta.setCiviliansEnabled(state);
- }
- clearSelfOwnedPeds();
-});
-
-// ---------------------------------------------------------------------------
-
-addNetworkHandler("ag.runCode", function(code, returnTo) {
- let returnValue = "Nothing";
- try {
- returnValue = eval("(" + code + ")");
- } catch(error) {
- triggerNetworkEvent("ag.runCodeFail", returnTo, code);
- return false;
- }
- triggerNetworkEvent("ag.runCodeSuccess", returnTo, code, returnValue);
-});
-
-// -------------------------------------------------------------------------
-
-function enterVehicleAsPassenger() {
- if(localPlayer.vehicle == null) {
- let tempVehicle = getClosestVehicle(localPlayer.position);
- if(tempVehicle != null) {
- localPlayer.enterVehicle(tempVehicle, false);
- }
- }
-}
-
-// -------------------------------------------------------------------------
-
-function getClosestVehicle(pos) {
- return getVehicles().reduce((i, j) => (i.position.distance(pos) < j.position.distance(pos)) ? i : j);
-}
-
-// -------------------------------------------------------------------------
-
-addNetworkHandler("ag.clearWeapons", function() {
- logToConsole(LOG_DEBUG, `[Asshat.Main] Clearing weapons`);
- localPlayer.clearWeapons();
- forceWeapon = 0;
- forceWeaponAmmo = 0;
- forceWeaponClipAmmo = 0;
-});
-
-// ---------------------------------------------------------------------------
-
-addNetworkHandler("ag.giveWeapon", function(weaponId, ammo, active) {
- logToConsole(LOG_DEBUG, `[Asshat.Main] Giving weapon ${weaponId} with ${ammo} ammo`);
- localPlayer.giveWeapon(weaponId, ammo, active);
- forceWeaponAmmo = localPlayer.getWeaponAmmunition(getWeaponSlot(weaponId));
- forceWeaponClipAmmo = localPlayer.getWeaponClipAmmunition(getWeaponSlot(weaponId));
- forceWeapon = weaponId;
-});
-
-// ---------------------------------------------------------------------------
-
-addEventHandler("OnElementStreamIn", function(event, element) {
- switch(element.type) {
- case ELEMENT_VEHICLE:
- syncVehicleProperties(element);
- break;
-
- case ELEMENT_CIVILIAN:
- syncCivilianProperties(element);
- break;
-
- case ELEMENT_PLAYER:
- syncPlayerProperties(element);
- break;
-
- case ELEMENT_OBJECT:
- //syncObjectProperties(element);
- break;
-
- default:
- break;
- }
-});
-
-// ---------------------------------------------------------------------------
-
-addNetworkHandler("ag.blips", function(blipData) {
- for(let i in blipData) {
- allServerBlips.push(blipData[i]);
- }
-});
-
-// ---------------------------------------------------------------------------
-
-function showIslandBlips() {
- for(let i in allServerBlips) {
- let position = toVector3(allServerBlips[i][1], allServerBlips[i][2], allServerBlips[i][3]);
- if(getIslandFromPosition(position) == getIslandFromPosition(localPlayer.position)) {
- let tempBlip = createBlip(position, allServerBlips[i][0], allServerBlips[i][4], allServerBlips[i][5]);
- currentServerBlips.push(tempBlip);
- }
- }
-}
-
-// ---------------------------------------------------------------------------
-
-function getIslandFromPosition(position) {
- switch(gta.game) {
- case GAME_GTA_III:
- if(position.x > 616) {
- return 1;
- } else if(position.x < -283) {
- return 3;
- }
- return 2;
-
- default:
- return 0;
- }
-}
-
-// ---------------------------------------------------------------------------
-
-addEventHandler("onPedSpawn", function(event, ped) {
- // Nasty workaround since localPlayer is null as the player spawns (reported as client bug #194)
- setTimeout(initLocalPlayer, 500, ped);
-});
-
-// ---------------------------------------------------------------------------
-
-function attemptToShowBlipsOnSpawn(ped) {
- if(ped == localPlayer) {
- showIslandBlips();
- }
-}
-
-// ---------------------------------------------------------------------------
-
-addNetworkHandler("ag.skin", function(skin) {
- localPlayer.skin = skin;
-});
-
-// ---------------------------------------------------------------------------
-
-addNetworkHandler("ag.pedSkin", function(ped, skin) {
- ped.skin = skin;
-});
-
-// ---------------------------------------------------------------------------
-
-addNetworkHandler("ag.position", function(position) {
- localPlayer.position = position;
-});
-
-// ---------------------------------------------------------------------------
-
-addNetworkHandler("ag.heading", function(heading) {
- localPlayer.heading = heading;
-});
-
-// ---------------------------------------------------------------------------
-
-addNetworkHandler("ag.interior", function(interior) {
- localPlayer.interior = interior;
- gta.cameraInterior = interior;
-});
-
-// ---------------------------------------------------------------------------
-
-addNetworkHandler("ag.dimension", function(dimension) {
- localPlayer.dimension = dimension;
-});
-
-// ---------------------------------------------------------------------------
-
-addNetworkHandler("ag.removeFromVehicle", function() {
- localPlayer.removeFromVehicle();
-});
-
-// ---------------------------------------------------------------------------
-
-function initLocalPlayer(player) {
- addEventHandler("onProcess", processEvent);
-}
-
-// ---------------------------------------------------------------------------
-
-function processEvent(event, deltaTime) {
- gta.clearMessages();
-
- if(localPlayer != null) {
- localPlayer.wantedLevel = 0;
-
- let position = localPlayer.position;
- if(localPlayer.vehicle) {
- position = localPlayer.vehicle.position;
- }
-
- if(inVehicle && localPlayer.vehicle != null) {
- if(!localPlayer.vehicle.engine) {
- 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 {
- if(parkedVehiclePosition) {
- parkedVehiclePosition = false;
- parkedVehicleHeading = false;
- }
- }
- }
-
- getElementsByType(ELEMENT_PICKUP).forEach(function(pickup) {
- if(pickup.isOwner) {
- destroyElement(pickup);
- }
- });
-
- getElementsByType(ELEMENT_MARKER).forEach(function(sphere) {
- if(position.distance(sphere.position) <= sphere.radius) {
- if(!inSphere) {
- inSphere = sphere;
- triggerEvent("OnLocalPlayerEnterSphere", null, sphere);
- //triggerNetworkEvent("ag.onPlayerEnterSphere", sphere);
- }
- } else {
- if(inSphere) {
- inSphere = false;
- triggerEvent("OnLocalPlayerExitSphere", null, sphere);
- //triggerNetworkEvent("ag.onPlayerExitSphere", sphere);
- }
- }
- });
-
- if(gta.game == GAME_GTA_SA) {
- if(jobRouteStopSphere != null) {
- if(position.distance(jobRouteStopSphere.position) <= 2.0) {
- enteredJobRouteSphere();
- }
- }
- }
-
- if(localPlayer.vehicle) {
- if(!inVehicle) {
- inVehicle = localPlayer.vehicle;
- inVehicleSeat = getLocalPlayerVehicleSeat();
- triggerEvent("OnLocalPlayerEnteredVehicle", inVehicle, inVehicleSeat);
- }
- } else {
- if(inVehicle) {
- triggerEvent("OnLocalPlayerExitedVehicle", inVehicle, inVehicleSeat);
- inVehicle = false;
- inVehicleSeat = false;
- }
- }
-
- if(forceWeapon != 0) {
- if(localPlayer.weapon != forceWeapon) {
- localPlayer.weapon = forceWeapon;
- localPlayer.setWeaponClipAmmunition(getWeaponSlot(forceWeapon), forceWeaponClipAmmo);
- localPlayer.setWeaponAmmunition(getWeaponSlot(forceWeapon), forceWeaponAmmo);
- } else {
- forceWeaponClipAmmo = localPlayer.getWeaponClipAmmunition(getWeaponSlot(forceWeapon));
- forceWeaponAmmo = localPlayer.getWeaponAmmunition(getWeaponSlot(forceWeapon));
- }
- } else {
- if(localPlayer.weapon > 0) {
- localPlayer.clearWeapons();
- }
- }
- }
-}
-
-// ---------------------------------------------------------------------------
-
-addEventHandler("OnDrawnHUD", function (event) {
- if(!renderHUD) {
- return false;
- }
-
- if(localPlayer == null) {
- return false;
- }
-
- if(renderSmallGameMessage) {
- if(smallGameMessageFont != null) {
- if(smallGameMessageFont != "") {
- smallGameMessageFont.render(smallGameMessageText, [0, gta.height-50], gta.width, 0.5, 0.0, smallGameMessageFont.size, smallGameMessageColour, true, true, false, true);
- }
- }
- }
-
- if(renderLogo) {
- if(logoImage != null) {
- drawing.drawRectangle(logoImage, logoPos, logoSize);
- }
- }
-
- if(renderScoreboard) {
- if(isKeyDown(SDLK_TAB)) {
- processScoreboardRendering();
- }
- }
-
- if(renderLabels) {
- processLabelRendering();
- }
-
- if(renderItemActionDelay) {
- //logToConsole(LOG_DEBUG, `Item action delay render enabled`);
- if(itemActionDelayEnabled) {
- //logToConsole(LOG_DEBUG, `Item action delay enabled`);
- let finishTime = itemActionDelayStart+itemActionDelayDuration;
- if(sdl.ticks >= finishTime) {
- logToConsole(LOG_DEBUG, `Item action delay finish time reached`);
- itemActionDelayEnabled = false;
- itemActionDelayDuration = 0;
- itemActionDelayStart = 0;
- triggerNetworkEvent("ag.itemActionDelayComplete");
- } else {
- let progressWidth = itemActionDelaySize.x-Math.ceil((finishTime-sdl.ticks)/100);
- logToConsole(LOG_DEBUG, `Item action delay in progress - ${Math.ceil((finishTime-sdl.ticks)/100)} - ${progressWidth}/${itemActionDelaySize.x}`);
- drawing.drawRectangle(null, [itemActionDelayPosition.x-(itemActionDelaySize.x/2), itemActionDelayPosition.y-(itemActionDelaySize.y/2)], [progressWidth, itemActionDelaySize.y], COLOUR_LIME, COLOUR_LIME, COLOUR_LIME, COLOUR_LIME);
- }
- }
- }
-});
-
-// ---------------------------------------------------------------------------
-
-function openAllGarages() {
- switch(gta.game) {
- case GAME_GTA_III:
- for(let i=0;i<=26;i++) {
- openGarage(i);
- }
- break;
-
- case GAME_GTA_VC:
- for(let i=0;i<=32;i++) {
- openGarage(i);
- }
- break;
-
- case GAME_GTA_SA:
- for(let i=0;i<=44;i++) {
- openGarage(i);
- }
- break;
-
- default:
- break;
- }
-}
-
-// ---------------------------------------------------------------------------
-
-function closeAllGarages() {
- switch(gta.game) {
- case GAME_GTA_III:
- for(let i=0;i<=26;i++) {
- closeGarage(i);
- }
- break;
-
- case GAME_GTA_VC:
- for(let i=0;i<=32;i++) {
- closeGarage(i);
- }
- break;
-
- case GAME_GTA_SA:
- for(let i=0;i<=44;i++) {
- closeGarage(i);
- }
- break;
-
- default:
- break;
- }
-}
-
-// ---------------------------------------------------------------------------
-
-addNetworkHandler("ag.freeze", function(state) {
- gui.showCursor(state, !state);
-});
-
-// ---------------------------------------------------------------------------
-
-addNetworkHandler("ag.control", function(controlState, cursorState = false) {
- gui.showCursor(cursorState, controlState);
-});
-
-// ---------------------------------------------------------------------------
-
-addNetworkHandler("ag.cursortoggle", function() {
- gui.showCursor(!gui.cursorEnabled, false);
-});
-
-// ---------------------------------------------------------------------------
-
-addNetworkHandler("ag.fadeCamera", function(state, time) {
- gta.fadeCamera(state, time);
-});
-
-// ---------------------------------------------------------------------------
-
-addEventHandler("OnPedWasted", function(event, wastedPed, killerPed, weapon, pedPiece) {
- wastedPed.clearWeapons();
-});
-
-// ---------------------------------------------------------------------------
-
-addNetworkHandler("ag.showBusStop", function(position, colour) {
- if(gta.game == GAME_GTA_SA) {
- jobRouteStopSphere = gta.createPickup(1318, position, 1);
- } else {
- jobRouteStopSphere = gta.createSphere(position, 3);
- jobRouteStopSphere.colour = colour;
- }
-
- jobRouteStopBlip = gta.createBlip(position, 0, 2, colour);
-});
-
-// ---------------------------------------------------------------------------
-
-addNetworkHandler("ag.snow", function(fallingSnow, groundSnow) {
- if(!isNull(snowing)) {
- snowing = fallingSnow;
- forceSnowing(groundSnow);
- }
-});
-
-// ---------------------------------------------------------------------------
-
-addNetworkHandler("ag.money", function(amount) {
- localPlayer.money = amount;
-});
-
-// ---------------------------------------------------------------------------
-
-addNetworkHandler("ag.removeWorldObject", function(model, position, range) {
- logToConsole(LOG_DEBUG, `Removing world object ${model} at X: ${position.x}, Y: ${position.x}, Z: ${position.x} with range of ${range}`);
- gta.removeWorldObject(model, position, range);
-});
-
-// ---------------------------------------------------------------------------
-
-addNetworkHandler("ag.excludeGroundSnow", function(model) {
- logToConsole(LOG_DEBUG, `Disabling ground snow for object model ${model}`);
- groundSnow.excludeModel(model);
-});
-
-// ---------------------------------------------------------------------------
-
-addEventHandler("OnLocalPlayerEnterSphere", function(event, sphere) {
- if(sphere == jobRouteStopSphere) {
- enteredJobRouteSphere();
- }
-});
-
-// ---------------------------------------------------------------------------
-
-addNetworkHandler("ag.smallGameMessage", function(text, colour, duration) {
- if(smallGameMessageText != "") {
- clearTimeout(smallGameMessageTimer);
- }
-
- smallGameMessageColour = colour;
- smallGameMessageText = text;
-
- smallGameMessageTimer = setTimeout(function() {
- smallGameMessageText = "";
- smallGameMessageColour = COLOUR_WHITE;
- smallGameMessageTimer = null;
- }, duration);
-});
-
-// ---------------------------------------------------------------------------
-
-function enteredJobRouteSphere() {
- triggerNetworkEvent("ag.arrivedAtBusStop");
- destroyElement(jobRouteStopSphere);
- destroyElement(jobRouteStopBlip);
- jobRouteStopSphere = null;
- jobRouteStopBlip = null;
-}
-
-// ---------------------------------------------------------------------------
-
-addNetworkHandler("ag.jobType", function(tempJobType) {
- logToConsole(LOG_INFO, `[Asshat.Main] Set local player job type to ${tempJobType}`);
- localPlayerJobType = tempJobType;
-});
-
-// ---------------------------------------------------------------------------
-
-addNetworkHandler("ag.working", function(tempWorking) {
- localPlayerWorking = tempWorking;
-});
-
-// ---------------------------------------------------------------------------
-
-addNetworkHandler("ag.spawned", function(client, state) {
- isSpawned = state;
- syncPlayerProperties(localPlayer);
-});
-
-// ---------------------------------------------------------------------------
-
-addNetworkHandler("ag.weaponDamageEvent", function(clientName, eventType) {
- logToConsole(LOG_INFO, `[Asshat.Main] Set ${clientName} damage event type to ${eventType}`);
- weaponDamageEvent[clientName] = eventType;
-});
-
-// ---------------------------------------------------------------------------
-
-addNetworkHandler("ag.weaponDamageEnabled", function(clientName, state) {
- logToConsole(LOG_INFO, `[Asshat.Main] ${(state)?"Enabled":"Disabled"} damage from ${clientName}`);
- weaponDamageEnabled[clientName] = state;
-});
-
-// ---------------------------------------------------------------------------
-
-addNetworkHandler("ag.mouseCamera", function(state) {
- logToConsole(LOG_INFO, `[Asshat.Main] ${(state)?"Enabled":"Disabled"} mouse camera`);
- mouseCameraEnabled = !mouseCameraEnabled;
- SetStandardControlsEnabled(!mouseCameraEnabled);
-});
-
-// ---------------------------------------------------------------------------
-
-function clearSelfOwnedPeds() {
- logToConsole(LOG_DEBUG, `Clearing self-owned peds`);
- getElementsByType(ELEMENT_CIVILIAN).forEach(function(ped) {
- if(ped.isOwner) {
- destroyElement(ped);
- }
- });
-}
-
-// ---------------------------------------------------------------------------
-
-addNetworkHandler("ag.set2DRendering", function(hudState, labelState, smallGameMessageState, scoreboardState, hotBarState, itemActionDelayState) {
- renderHUD = hudState;
- setHUDEnabled(hudState);
-
- renderLabels = labelState;
- renderSmallGameMessage = smallGameMessageState;
- renderScoreboard = scoreboardState;
- renderHotBar = hotBarState;
- renderItemActionDelay = itemActionDelayState;
-});
-
-// ---------------------------------------------------------------------------
-
-function getLocalPlayerVehicleSeat() {
- for(let i = 0 ; i <= 4 ; i++) {
- if(localPlayer.vehicle.getOccupant(i) == localPlayer) {
- return i;
- }
- }
-}
-
-// ---------------------------------------------------------------------------
-
-addEventHandler("OnPedInflictDamage", function(event, damagedPed, damagerEntity, weaponId, healthLoss, pedPiece) {
- if(damagedPed == localPlayer) {
- if(!weaponDamageEnabled[damagerEntity.name]) {
- event.preventDefault();
- triggerNetworkEvent(player, "ag.weaponDamage", damagerEntity, weaponId, pedPiece);
- }
- }
-});
-
-// ---------------------------------------------------------------------------
-
-addEventHandler("OnLocalPlayerExitedVehicle", function(event, vehicle, seat) {
- triggerNetworkEvent("ag.onPlayerExitVehicle");
- if(inVehicleSeat) {
- parkedVehiclePosition = false;
- parkedVehicleHeading = false;
- }
-});
-
-// ---------------------------------------------------------------------------
-
-addEventHandler("OnLocalPlayerEnteredVehicle", function(event, vehicle, seat) {
- triggerNetworkEvent("ag.onPlayerEnterVehicle");
-
- if(inVehicleSeat == 0) {
- if(inVehicle.owner != -1) {
- inVehicle.engine = false;
- if(!inVehicle.engine) {
- parkedVehiclePosition = inVehicle.position;
- parkedVehicleHeading = inVehicle.heading;
- }
- }
- }
-});
-
-// ---------------------------------------------------------------------------
-
-addNetworkHandler("ag.showItemActionDelay", function(duration) {
- itemActionDelayDuration = duration;
- itemActionDelayStart = sdl.ticks;
- itemActionDelayEnabled = true;
- logToConsole(LOG_DEBUG, `Item action delay event called. Duration: ${itemActionDelayDuration}, Start: ${itemActionDelayStart}, Render: ${renderItemActionDelay}`);
-});
-
-// ---------------------------------------------------------------------------
-
-function getWeaponSlot(weaponId) {
- return getGameData().weaponSlots[gta.game][weaponId];
-}
-
-// ---------------------------------------------------------------------------
-
-addNetworkHandler("ag.drunkEffect", function(amount, duration) {
- drunkEffectAmount = 0;
- drunkEffectDurationTimer = setInterval(function() {
- drunkEffectAmount = drunkEffectAmount;
- if(drunkEffectAmount > 0) {
- gta.SET_MOTION_BLUR(drunkEffectAmount);
- } else {
- clearInterval(drunkEffectDurationTimer);
- drunkEffectDurationTimer = null;
- }
- }, 1000);
-});
-
-// ---------------------------------------------------------------------------
-
-addNetworkHandler("ag.clearPedState", function() {
- localPlayer.clearObjective();
-});
-
-// ---------------------------------------------------------------------------
\ No newline at end of file
+// ===========================================================================
\ No newline at end of file
diff --git a/scripts/client/messaging.js b/scripts/client/messaging.js
new file mode 100644
index 00000000..ebc9ee3e
--- /dev/null
+++ b/scripts/client/messaging.js
@@ -0,0 +1,80 @@
+// ===========================================================================
+// Asshat-Gaming Roleplay
+// https://github.com/VortrexFTW/gtac_asshat_rp
+// Copyright (c) 2021 Asshat-Gaming (https://asshatgaming.com)
+// ===========================================================================
+// FILE: messaging.js
+// DESC: Provides messaging/textdraw functions and usage
+// TYPE: Client (JavaScript)
+// ===========================================================================
+
+let smallGameMessageFont = null;
+let smallGameMessageText = "";
+let smallGameMessageColour = COLOUR_WHITE;
+let smallGameMessageTimer = null;
+
+// ===========================================================================
+
+function initMessagingScript() {
+ logToConsole(LOG_DEBUG, "[Asshat.Messaging]: Initializing messaging script ...");
+ smallGameMessageFont = loadSmallGameMessageFont();
+ logToConsole(LOG_DEBUG, "[Asshat.Messaging]: Messaging script initialized!");
+}
+
+// ===========================================================================
+
+function loadSmallGameMessageFont() {
+ let tempSmallGameMessageFont = null;
+ let fontStream = openFile("files/fonts/pricedown.ttf");
+ if(fontStream != null) {
+ tempSmallGameMessageFont = lucasFont.createFont(fontStream, 20.0);
+ fontStream.close();
+ }
+
+ return tempSmallGameMessageFont;
+}
+
+// ===========================================================================
+
+function loadBigGameMessageFont() {
+ let tempBigGameMessageFont = null;
+ let fontStream = openFile("files/fonts/pricedown.ttf");
+ if(fontStream != null) {
+ tempBigGameMessageFont = lucasFont.createFont(fontStream, 28.0);
+ fontStream.close();
+ }
+
+ return tempBigGameMessageFont;
+}
+
+// ===========================================================================
+
+function processSmallGameMessageRendering() {
+ if(renderSmallGameMessage) {
+ if(smallGameMessageFont != null) {
+ if(smallGameMessageFont != "") {
+ smallGameMessageFont.render(smallGameMessageText, [0, gta.height-50], gta.width, 0.5, 0.0, smallGameMessageFont.size, smallGameMessageColour, true, true, false, true);
+ }
+ }
+ }
+}
+
+// ===========================================================================
+
+function showSmallGameMessage(text, colour, duration) {
+ logToConsole(LOG_DEBUG, `[Asshat.Messaging] Showing small game message '${text}' for ${duration}ms`);
+ if(smallGameMessageText != "") {
+ clearTimeout(smallGameMessageTimer);
+ }
+
+ smallGameMessageColour = colour;
+ smallGameMessageText = text;
+
+ smallGameMessageTimer = setTimeout(function() {
+ smallGameMessageText = "";
+ smallGameMessageColour = COLOUR_WHITE;
+ smallGameMessageTimer = null;
+ }, duration);
+}
+
+// ===========================================================================
\ No newline at end of file
diff --git a/scripts/client/mouse-camera.js b/scripts/client/mouse-camera.js
deleted file mode 100644
index 876f760e..00000000
--- a/scripts/client/mouse-camera.js
+++ /dev/null
@@ -1,725 +0,0 @@
-
-// ===========================================================================
-// Asshat-Gaming Roleplay
-// https://github.com/VortrexFTW/gtac_asshat_rp
-// Copyright (c) 2020 Asshat-Gaming (https://asshatgaming.com)
-// ---------------------------------------------------------------------------
-// FILE: mouse-camera.js
-// DESC: Provides a freelook camera similar to SA for III and VC
-// TYPE: Client (JavaScript)
-// ===========================================================================
-
-// CREDITS TO LUCASC190 FOR MAKING THE MOUSE CAMERA
-// WALKING CODE ADDED BY VORTREX
-
-function SetStandardControlsEnabled(bEnabled)
-{
- if (gta.standardControls === undefined)
- {
- console.warn("gta.standardControls not implemented");
- return;
- }
- gta.standardControls = bEnabled;
-}
-
-function GetCurrentPlayerIndex()
-{
- return 0;
-}
-
-function GetPlayerPed(uiIndex)
-{
- if (uiIndex >= 1)
- throw new Error("player index out of range");
- return localPlayer;
-}
-
-function GetPedVehicle(pPed)
-{
- return pPed.vehicle;
-}
-
-let ENTITYTYPE_BUILDING = 1;
-let ENTITYTYPE_VEHICLE = 2;
-let ENTITYTYPE_PED = 3;
-let ENTITYTYPE_OBJECT = 4;
-let ENTITYTYPE_DUMMY = 5;
-
-function GetEntityType(Entity)
-{
- if (Entity.isType(ELEMENT_BUILDING))
- return ENTITYTYPE_BUILDING;
- if (Entity.isType(ELEMENT_VEHICLE))
- return ENTITYTYPE_VEHICLE;
- if (Entity.isType(ELEMENT_PED))
- return ENTITYTYPE_PED;
- if (Entity.isType(ELEMENT_OBJECT))
- return ENTITYTYPE_OBJECT;
- //if (Entity.isType(ELEMENT_DUMMY))
- // return ENTITYTYPE_DUMMY;
- return undefined;
-}
-
-function GetPlaceableMatrix(pPlaceable)
-{
- if (pPlaceable == GetCamera())
- return gta.cameraMatrix;
- return pPlaceable.matrix;
-}
-
-function GetEntityModel(pEntity)
-{
- return pEntity;
-}
-
-function GetModelBoundingSphere(usModel)
-{
- return [usModel.boundingRadius, usModel.boundingCentre.x, usModel.boundingCentre.y, usModel.boundingCentre.z];
-}
-
-function GetMouseSpeed()
-{
- if (gui.cursorEnabled)
- return [0,0];
- let MouseSpeed = gta.getMouseSpeed();
- return [MouseSpeed.x,-MouseSpeed.y];
-}
-
-function GetMouseSensitivity()
-{
- if (gta.getMouseSensitivity === undefined)
- {
- //console.error("gta.getMouseSensitivity not implemented");
- return [0.0025,0.003];
- }
- let MouseSensitivity = gta.getMouseSensitivity();
- return [MouseSensitivity.x,MouseSensitivity.y];
-}
-
-let GetCamera;
-{
- const Camera = Symbol();
-
- GetCamera = function()
- {
- return Camera;
- }
-}
-
-function AreEntityCollisionsEnabled(pEntity)
-{
- return pEntity.collisionsEnabled;
-}
-
-function SetEntityCollisionsEnabled(pEntity, bCollisionsEnabled)
-{
- pEntity.collisionsEnabled = bCollisionsEnabled;
-}
-
-function ProcessLineOfSight(vecStartX, vecStartY, vecStartZ, vecEndX, vecEndY, vecEndZ, bCheckBuildings, bCheckVehicles, bCheckPeds, bCheckObjects, bCheckDummies, bCheckSeeThroughStuff, bIgnoreSomeObjectsForCamera)
-{
- if (gta.processLineOfSight === undefined)
- {
- console.warn("gta.processLineOfSight not implemented");
- return [null];
- }
- let Result = gta.processLineOfSight([vecStartX, vecStartY, vecStartZ], [vecEndX, vecEndY, vecEndZ], bCheckBuildings, bCheckVehicles, bCheckPeds, bCheckObjects, bCheckDummies, bCheckSeeThroughStuff, bIgnoreSomeObjectsForCamera);
- if (Result == null)
- return [null];
- return [Result.position.x, Result.position.y ,Result.position.z, Result.normal.x, Result.normal.y ,Result.normal.z, Result.entity];
-}
-
-function SetPlaceableMatrix(pPlaceable, mat)
-{
- if (pPlaceable == GetCamera())
- {
- gta.setCameraMatrix(mat);
- return;
- }
- pPlaceable.matrix = mat;
-}
-
-const UpdateCamera = gta.updateCamera;
-
-let GetTickCount;
-{
- let FrameCount = 0;
-
- setInterval(() =>
- {
- ++FrameCount;
- }, 0);
-
- let GTAFrameCount = 0;
-
- addEventHandler("OnProcess", (event, deltaTime) =>
- {
- ++GTAFrameCount;
- });
-
- GetTickCount = function(bGTA, bFrames)
- {
- if (bFrames)
- return bGTA ? GTAFrameCount : FrameCount;
- else
- return bGTA ? gta.tickCount : sdl.ticks;
- }
-}
-
-function easingSinusoidalInOut(t,b,c,d)//TODO: Move this to MathUtil.js
-{
- return -c/2 * (Math.cos((Math.PI)*t/d) - 1) + b;
-}
-
-//TODO: extract
-
-function applyMultiplierTimeStep(m,t)//TODO: Move this to MathUtil.js
-{
- return Math.max(Math.min(1.0-(1.0-m)*(t),1),0);
-}
-
-//TODO: getOffset
-//TODO: round
-//TODO: getNumberBetween
-//TODO: split
-//TODO: isWhiteSpaceCharacter
-//TODO: isControlCharacter
-//TODO: alert
-//TODO: confirm
-
-const identityMatrix = new Matrix4x4();
-if (identityMatrix.setIdentity === undefined)
-{
- identityMatrix.m11 = 1;
- identityMatrix.m12 = 0;
- identityMatrix.m13 = 0;
- identityMatrix.m14 = 0;
- identityMatrix.m21 = 0;
- identityMatrix.m22 = 1;
- identityMatrix.m23 = 0;
- identityMatrix.m24 = 0;
- identityMatrix.m31 = 0;
- identityMatrix.m32 = 0;
- identityMatrix.m33 = 1;
- identityMatrix.m34 = 0;
- identityMatrix.m41 = 0;
- identityMatrix.m42 = 0;
- identityMatrix.m43 = 0;
- identityMatrix.m44 = 1;
-}
-
-const cameraIdentityMatrix = new Matrix4x4();
-cameraIdentityMatrix.m11 = -1;
-cameraIdentityMatrix.m12 = 0;
-cameraIdentityMatrix.m13 = 0;
-cameraIdentityMatrix.m14 = 0;
-cameraIdentityMatrix.m21 = 0;
-cameraIdentityMatrix.m22 = 1;
-cameraIdentityMatrix.m23 = 0;
-cameraIdentityMatrix.m24 = 0;
-cameraIdentityMatrix.m31 = 0;
-cameraIdentityMatrix.m32 = 0;
-cameraIdentityMatrix.m33 = 1;
-cameraIdentityMatrix.m34 = 0;
-cameraIdentityMatrix.m41 = 0;
-cameraIdentityMatrix.m42 = 0;
-cameraIdentityMatrix.m43 = 0;
-cameraIdentityMatrix.m44 = 1;
-
-function createMultipliedMatrix()
-{
- let matrix = new Matrix4x4();
- matrix.setMultiply.apply(matrix, arguments);
- return matrix;
-}
-
-function createXRotationMatrix(x)
-{
- let matrix = new Matrix4x4();
- matrix.setRotateX(x);
- return matrix;
-}
-
-function createYRotationMatrix(x)
-{
- let matrix = new Matrix4x4();
- matrix.setRotateY(x);
- return matrix;
-}
-
-function createZRotationMatrix(z)
-{
- let matrix = new Matrix4x4();
- matrix.setRotateZ(z);
- return matrix;
-}
-
-function createTranslationMatrix(x,y,z)
-{
- let matrix = new Matrix4x4();
- matrix.setTranslate([x,y,z]);
- return matrix;
-}
-
-//TODO: createScaleMatrix
-
-function getDotProduct(x,y,z,x2,y2,z2)
-{
- return x*x2 + y*y2 + z*z2;
-}
-
-function getCrossProduct(x,y,z,x2,y2,z2)
-{
- return [y*z2-z*y2, z*x2-x*z2, x*y2-y*x2];
-}
-
-function getLength(x,y,z)
-{
- return Math.sqrt(getDotProduct(x,y,z,x,y,z));
-}
-
-function normalise(x,y,z)
-{
- let length = getLength(x,y,z);
- if (length == 0)
- throw new Error("an attempt was made to normalise a three dimensional vector with a length of zero");
- return [x/length, y/length, z/length];
-}
-
-function createLookAtLHMatrix(eyeX, eyeY, eyeZ, atX, atY, atZ, upX,upY,upZ)
-{
- let matrix = new Matrix4x4();
- let [lookX, lookY, lookZ] = normalise(atX-eyeX,atY-eyeY,atZ-eyeZ);
- let [rightX, rightY, rightZ] = normalise.apply(null,getCrossProduct(upX,upY,upZ,lookX, lookY, lookZ));
- [upX,upY,upZ] = getCrossProduct(lookX, lookY, lookZ,rightX, rightY, rightZ);
- matrix.m11 = rightX;
- matrix.m12 = rightY;
- matrix.m13 = rightZ;
- matrix.m14 = 0;
-
- matrix.m21 = lookX;
- matrix.m22 = lookY;
- matrix.m23 = lookZ;
- matrix.m24 = 0;
-
- matrix.m31 = upX;
- matrix.m32 = upY;
- matrix.m33 = upZ;
- matrix.m34 = 0;
-
- matrix.m41 = eyeX;
- matrix.m42 = eyeY;
- matrix.m43 = eyeZ;
- matrix.m44 = 1;
-
- matrix.m41 = eyeX;
- matrix.m42 = eyeY;
- matrix.m43 = eyeZ;
- matrix.m44 = 1;
- return matrix;
-}
-
-function getDifferenceBetweenAngles(current,target)
-{
- let f = (((target-current)+Math.PI)/(Math.PI*2));
- return ((f-Math.floor(f))*(Math.PI*2))-Math.PI;
-}
-
-let easeCamera = false;
-let easeStartTicks;
-let easeDuration;
-let easeStartPosX, easeStartPosY, easeStartPosZ;
-let easeStartLookX, easeStartLookY, easeStartLookZ;
-let easeStartUpX, easeStartUpY, easeStartUpZ;
-
-function getCameraPositionInfo(matrix)
-{
- return [matrix.m41, matrix.m42, matrix.m43, matrix.m21, matrix.m22, matrix.m23, matrix.m31, matrix.m32, matrix.m33];
-}
-
-function startCameraEase()
-{
- easeCamera = true;
- easeStartTicks = GetTickCount(true,false);
- easeDuration = 1000;
- let matrix = GetPlaceableMatrix(GetCamera());
- [easeStartPosX, easeStartPosY, easeStartPosZ, easeStartLookX, easeStartLookY, easeStartLookZ, easeStartUpX, easeStartUpY, easeStartUpZ] = getCameraPositionInfo(matrix);
-}
-
-function applyCameraEase(matrix)
-{
- if (!easeCamera)
- return matrix;
- let ease = (GetTickCount(true,false)-easeStartTicks)/easeDuration;
- if (ease < 1)
- {
- ease = easingSinusoidalInOut(ease,0,1,1);
- let [newPosX, newPosY, newPosZ, newLookX, newLookY, newLookZ, newUpX, newUpY, newUpZ] = getCameraPositionInfo(matrix);
- let easePosX = easeStartPosX+(newPosX-easeStartPosX)*ease;
- let easePosY = easeStartPosY+(newPosY-easeStartPosY)*ease;
- let easePosZ = easeStartPosZ+(newPosZ-easeStartPosZ)*ease;
- let easeLookX = easeStartLookX+(newLookX-easeStartLookX)*ease;
- let easeLookY = easeStartLookY+(newLookY-easeStartLookY)*ease;
- let easeLookZ = easeStartLookZ+(newLookZ-easeStartLookZ)*ease;
- let easeUpX = easeStartUpX+(newUpX-easeStartUpX)*ease;
- let easeUpY = easeStartUpY+(newUpY-easeStartUpY)*ease;
- let easeUpZ = easeStartUpZ+(newUpZ-easeStartUpZ)*ease;
- return createLookAtLHMatrix(easePosX,easePosY,easePosZ,easePosX+easeLookX,easePosY+easeLookY,easePosZ+easeLookZ,easeUpX,easeUpY,easeUpZ);
- }
- return matrix;
-}
-
-function isCameraEasing()
-{
- return easeCamera && GetTickCount(true,false) < (easeStartTicks+easeDuration);
-}
-
-let oldCameraTarget = null;
-let OldPosition = null;//2019 Lucas was here!
-let cameraRotZ;
-let cameraRotY;
-
-function getCameraTarget()
-{
- let playerPed = GetPlayerPed(GetCurrentPlayerIndex());
- let vehicle = GetPedVehicle(playerPed);
- if (vehicle != null)
- return vehicle;
- if (playerPed != null)
- {
- //if (playerPed.health <= 1)//Breaks because of fade//2019 Lucas was here!
- // return null;
- return playerPed;
- }
- return null;
-}
-
-function isRelativeToTarget(target)
-{
- if (GetEntityType(target) == ENTITYTYPE_PED)
- return false;
- return false
-}
-
-function isClipped(target)
-{
- if (GetEntityType(target) == ENTITYTYPE_PED)
- return true;
- return true;
-}
-
-//2019 Lucas was here!
-function ShouldReturnToRestRotation(Target)
-{
- if (GetEntityType(Target) == ENTITYTYPE_PED)
- return false;
- return true;
-}
-
-function getCameraRestRotation(target)
-{
- let targetMatrix = GetPlaceableMatrix(target);
- let rotZ;
- if (isRelativeToTarget(target))
- rotZ = 0;
- else
- rotZ = -Math.atan2(targetMatrix.m21,targetMatrix.m22);
- let rotY = -0.2;
- return [rotZ, rotY];
-}
-
-function resetCameraRotation()
-{
- [cameraRotZ, cameraRotY] = getCameraRestRotation(getCameraTarget());
-}
-
-//2019 Lucas was here!
-let DeltaTime = 0;
-addEventHandler("OnProcess", (event, deltaTime) =>
-{
- DeltaTime = deltaTime;
- if(!localPlayer) {
- return false;
- }
-
- if(gta.game >= GAME_GTA_SA) {
- // We don't need this for GTA SA+
- return false;
- }
-
- /*
- if(localPlayer.vehicle == null) {
- let newAngle = 0.0;
- let moveKeyHeld = false;
- if(isKeyDown(SDLK_w)) {
- newAngle = Math.PI;
- moveKeyHeld = true;
- if(isKeyDown(SDLK_a)) {
- newAngle = newAngle+Math.PI/4;
- } else if(isKeyDown(SDLK_d)) {
- newAngle = newAngle-Math.PI/4;
- }
- } else if(isKeyDown(SDLK_s)) {
- newAngle = Math.PI*2;
- moveKeyHeld = true;
- if(isKeyDown(SDLK_a)) {
- newAngle = newAngle-Math.PI/4;
- } else if(isKeyDown(SDLK_d)) {
- newAngle = newAngle+Math.PI/4;
- }
- } else if(isKeyDown(SDLK_a)) {
- newAngle = -Math.PI/2;
- moveKeyHeld = true;
- } else if(isKeyDown(SDLK_d)) {
- newAngle = Math.PI/2;
- moveKeyHeld = true;
- }
-
- if(moveKeyHeld && !gui.cursorEnabled) {
- localPlayer.heading = cameraAngle + newAngle;
- }
-
- if(sdl.getModState()&KMOD_ALT && !gui.cursorEnabled) {
- if(moveKeyHeld) {
- let position = getPosInFrontOfPos(localPlayer.position, localPlayer.heading, 1.0);
- localPlayer.walkTo(vec3ToVec2(position));
- isWalking = true;
- triggerNetworkEvent("ag.walk", true);
- } else {
- isWalking = false;
- triggerNetworkEvent("ag.walk", false);
- }
- } else {
- isWalking = false;
- triggerNetworkEvent("ag.walk", false);
- }
- }
- */
-});
-
-let IdleTime = 0;//2019 Lucas was here!
-
-function processReturnToRestRotation()
-{
- //resetCameraRotation();//2019 Lucas was here!
-
- //2019 Lucas was here!
- let Target = getCameraTarget();
- if (!ShouldReturnToRestRotation(Target))
- return;
- IdleTime += DeltaTime;
- if (IdleTime > 1.5)
- {
- let Velocity = Target.velocity;
- let Matrix = Target.matrix;
- let Speed = getDotProduct(Velocity.x,Velocity.y,Velocity.z,Matrix.getElement(1*4+0),Matrix.getElement(1*4+1),Matrix.getElement(1*4+2));
- let AbsSpeed = Math.abs(Speed);
- let Multiplier = Math.min(AbsSpeed/0.75, 1);
- if (Multiplier != 0)
- {
- let [TargetCameraRotZ2, TargetCameraRotY2] = getCameraRestRotation(Target);
- if (Speed < 0)
- TargetCameraRotZ2 += Math.PI;
- let TimeStep = gta.timeStep/50*60;
- cameraRotZ += getDifferenceBetweenAngles(cameraRotZ,TargetCameraRotZ2)*applyMultiplierTimeStep(1/20,TimeStep)*Multiplier;
- cameraRotY += getDifferenceBetweenAngles(cameraRotY,TargetCameraRotY2)*applyMultiplierTimeStep(1/20,TimeStep)*Multiplier;
- }
- }
-}
-
-function cancelReturnToRestRotation()
-{
- IdleTime = 0;//2019 Lucas was here!
-}
-
-let distance;
-let zIncrease;
-
-function getCameraOffsetInfo(target)
-{
- if (GetEntityType(target) == ENTITYTYPE_PED)
- {
- let distance = 4;
- let zIncrease = 0.8;
- let offsetX = 0;
- let offsetY = 0;
- let offsetZ = 0;
- return [distance, zIncrease, offsetX, offsetY, offsetZ];
- }
- let model = GetEntityModel(target);
- let [radius] = GetModelBoundingSphere(model);
- let minDistance;
- let maxDistance;
- let minZIncrease;
- let maxZIncrease;
- let minRadius;
- let maxRadius;
- let offsetX;
- let offsetY;
- let offsetZ;
- if (radius <= 3.0535011291504)
- {
- minDistance = 4;
- maxDistance = 8;
- minZIncrease = 0.5;
- maxZIncrease = 1;
- minRadius = 2;
- maxRadius = 3.0535011291504;
- }
- else
- {
- minDistance = 8;
- maxDistance = 16;
- minZIncrease = 1;
- maxZIncrease = 2;
- minRadius = 3.05350112915042;
- maxRadius = 6.3955960273743;
- }
- offsetX = 0;
- offsetY = 0;
- offsetZ = 0;
- distance = minDistance+(radius-minRadius)/(maxRadius-minRadius)*(maxDistance-minDistance);
- zIncrease = minZIncrease+(radius-minRadius)/(maxRadius-minRadius)*(maxZIncrease-minZIncrease);
- return [distance, zIncrease, offsetX, offsetY, offsetZ];
-}
-
-function update()
-{
- let target = getCameraTarget();
- if (target != null)
- {
- if (oldCameraTarget != target)
- {
- //if (oldCameraTarget != null)//2019 Lucas was here!
- let Position = target.position;
- if (OldPosition == null || getLength(Position.x-OldPosition.x,Position.y-OldPosition.y,Position.z-OldPosition.z) < 10)
- startCameraEase()
- resetCameraRotation()
- }
- let [mouseSpeedX, mouseSpeedY] = GetMouseSpeed();
- let [mouseSensitivityX, mouseSensitivityY] = GetMouseSensitivity();
- mouseSpeedX = mouseSpeedX*mouseSensitivityX*2;
- mouseSpeedY = mouseSpeedY*mouseSensitivityY*2;
- if (mouseSpeedX == 0 && mouseSpeedY == 0)
- {
- processReturnToRestRotation();
- }
- else
- {
- cameraRotZ = cameraRotZ-mouseSpeedX;
- cameraRotY = cameraRotY-mouseSpeedY;
- cancelReturnToRestRotation();
- }
- cameraRotY = Math.max(cameraRotY,-Math.PI/2+0.01);
- if (GetEntityType(target) != ENTITYTYPE_PED)
- cameraRotY = Math.min(cameraRotY,Math.PI/8.5);//2019 Lucas was here!
- else
- cameraRotY = Math.min(cameraRotY,Math.PI/4);
- let camera = GetCamera();
- let targetMatrix = GetPlaceableMatrix(target);
- let [distance, zIncrease, offsetX, offsetY, offsetZ] = getCameraOffsetInfo(target);
- let offsetTranslationMatrix = createTranslationMatrix(offsetX, offsetY, offsetZ);
- targetMatrix = createMultipliedMatrix(offsetTranslationMatrix,targetMatrix);
- let targetPosX, targetPosY, targetPosZ;
- if (isRelativeToTarget(target))
- [targetPosX, targetPosY, targetPosZ] = [0,0,0];
- else
- [targetPosX, targetPosY, targetPosZ] = [targetMatrix.m41,targetMatrix.m42,targetMatrix.m43];
- let distanceTranslationMatrix = createTranslationMatrix(0,-distance,0);
- targetPosZ = targetPosZ+zIncrease;
- let targetTranslationMatrix = createTranslationMatrix(targetPosX, targetPosY, targetPosZ);
- let offsetRotationX = createXRotationMatrix(cameraRotY);
- let offsetRotationZ = createZRotationMatrix(cameraRotZ);
- let cameraMatrix = createMultipliedMatrix(cameraIdentityMatrix,distanceTranslationMatrix,offsetRotationX,offsetRotationZ,targetTranslationMatrix);
- if (isRelativeToTarget(target))
- {
- cameraMatrix = createMultipliedMatrix(cameraMatrix,targetMatrix);
- targetTranslationMatrix = createMultipliedMatrix(targetTranslationMatrix,targetMatrix);
- }
- if (isClipped(target))
- {
- let startX = targetTranslationMatrix.m41;
- let startY = targetTranslationMatrix.m42;
- let startZ = targetTranslationMatrix.m43;
- let endX = cameraMatrix.m41;
- let endY = cameraMatrix.m42;
- let endZ = cameraMatrix.m43;
- let checkBuildings = true;
- let checkVehicles = true;
- let checkPeds = true;
- let checkObjects = true;
- let checkDummies = false;
- let checkSeeThroughStuff = false;
- let ignoreSomeObjectsForCamera = true;
- let collisionsEnabled = AreEntityCollisionsEnabled(target);
- if (collisionsEnabled)
- SetEntityCollisionsEnabled(target,false);
- let [positionX,positionY,positionZ,normalX,normalY,normalZ,targetEntity] = ProcessLineOfSight(startX,startY,startZ,endX,endY,endZ,checkBuildings,checkVehicles,checkPeds,checkObjects,checkDummies,checkSeeThroughStuff,ignoreSomeObjectsForCamera);
- if (collisionsEnabled)
- SetEntityCollisionsEnabled(target,true);
- if (positionX != null)
- {
- //2019 Lucas was here!
- let Distance = 0.3;
- positionX += normalX*Distance;
- positionY += normalY*Distance;
- positionZ += normalZ*Distance;
-
- cameraMatrix.m41 = positionX;
- cameraMatrix.m42 = positionY;
- cameraMatrix.m43 = positionZ;
- }
- }
- if (isCameraEasing())
- cameraMatrix = applyCameraEase(cameraMatrix);
- SetPlaceableMatrix(camera,cameraMatrix);
- UpdateCamera(camera);
- }
- oldCameraTarget = target;
- OldPosition = (target != null) ? target.position : null;//2019 Lucas was here!
- return target != null;
-}
-
-addEventHandler("OnCameraProcess", (event) =>
-{
- if(mouseCameraEnabled) {
- update();
- event.preventDefault();
- }
-});
-
-function getPosInFrontOfPos(pos, angle, distance) {
- let x = (pos.x+((Math.cos(angle+(Math.PI/2)))*distance));
- let y = (pos.y+((Math.sin(angle+(Math.PI/2)))*distance));
- let z = pos.z;
-
- return new Vec3(x,y,z);
-}
-
-function vec3ToVec2(pos) {
- return new Vec2(pos[0], pos[1]);
-}
-
-/*
-addEventHandler("OnEntityProcess", function(event, entity) {
- if(entity.type == ELEMENT_PLAYER) {
- if(entity != localPlayer) {
- let isPlayerWalking = entity.getData("ag.walk");
- if(isPlayerWalking == true) {
- let position = getPosInFrontOfPos(entity.position, entity.heading, 1.0);
- entity.walkTo(position);
- }
- }
- }
-});
-
-function getHeadingFromPosToPos(pos1, pos2) {
- let x = pos2.x-pos1.x;
- let y = pos2.y-pos1.y;
- let rad = Math.atan2(y, x);
- let deg = radToDeg(rad);
- deg -= 90;
- deg = deg % 360;
- return degToRad(deg);
-}
-*/
\ No newline at end of file
diff --git a/scripts/client/nametag.js b/scripts/client/nametag.js
index a2111f9e..732d8595 100644
--- a/scripts/client/nametag.js
+++ b/scripts/client/nametag.js
@@ -1,8 +1,8 @@
// ===========================================================================
// Asshat-Gaming Roleplay
// https://github.com/VortrexFTW/gtac_asshat_rp
-// Copyright (c) 2020 Asshat-Gaming (https://asshatgaming.com)
-// ---------------------------------------------------------------------------
+// Copyright (c) 2021 Asshat-Gaming (https://asshatgaming.com)
+// ===========================================================================
// FILE: nametags.js
// DESC: Provides nametag rendering
// TYPE: Client (JavaScript)
@@ -20,31 +20,52 @@ let playerColours = {};
let playerPaused = {};
let playerPing = {};
-// -------------------------------------------------------------------------
+// ===========================================================================
-addEventHandler("OnResourceReady", function(event, resource) {
- if (resource == thisResource) {
- nametagFont = lucasFont.createDefaultFont(12.0, "Roboto", "Light");
- afkStatusFont = lucasFont.createDefaultFont(18.0, "Roboto", "Light");
- }
-});
+function initNameTagScript() {
+ logToConsole(LOG_DEBUG, "[Asshat.NameTag]: Initializing nametag script ...");
+ nametagFont = loadNameTagFont();
+ afkStatusFont = loadPausedStatusFont();
+ logToConsole(LOG_DEBUG, "[Asshat.NameTag]: Nametag script initialized!");
+}
-// -------------------------------------------------------------------------
+// ===========================================================================
-addNetworkHandler("ag.nametag", function(clientName, characterName, colour, paused, ping) {
+function loadNameTagFont() {
+ return lucasFont.createDefaultFont(12.0, "Roboto", "Light");
+}
+
+// ===========================================================================
+
+function loadPausedStatusFont() {
+ return lucasFont.createDefaultFont(18.0, "Roboto", "Light");
+}
+
+// ===========================================================================
+
+function updatePlayerNameTag(clientName, characterName, colour, paused, ping) {
playerNames[clientName] = characterName;
playerColours[clientName] = colour;
playerPaused[clientName] = paused;
playerPing[clientName] = ping;
-});
-// -------------------------------------------------------------------------
+ if(gta.game == GAME_GTA_IV) {
+ let client = getPlayerFromParams(clientName);
+ if(client != false) {
+ if(client.player != null) {
+ client.player.setNametag(characterName, colour);
+ }
+ }
+ }
+}
-addNetworkHandler("ag.ping", function(clientName, ping) {
+// ===========================================================================
+
+function updatePlayerPing(clientName, ping) {
playerPing[clientName] = ping;
-});
+}
-// -------------------------------------------------------------------------
+// ===========================================================================
function drawNametag(x, y, health, armour, text, ping, alpha, distance, colour, afk, skin) {
if(nametagFont == null) {
@@ -75,9 +96,9 @@ function drawNametag(x, y, health, armour, text, ping, alpha, distance, colour,
let hx = x-width/2;
let hy = y-10/2;
let colourB = toColour(0, 0, 0, Math.floor(255.0*alpha)); // Background colour (black)
- drawing.drawRectangle(null, [hx, hy], [width, 8], colourB, colourB, colourB, colourB);
- let colour = toColour(Math.floor(255.0*alpha), Math.floor(255.0-(health*255.0)), Math.floor(health*255.0), 0); // Health bar colour (varies, depending on health)
- drawing.drawRectangle(null, [hx+2, hy+2], [(width-4)*health, 10-6], colour, colour, colour, colour);
+ graphics.drawRectangle(null, [hx, hy], [width, 8], colourB, colourB, colourB, colourB);
+ let colour = toColour(Math.floor(255.0-(health*255.0)), Math.floor(health*255.0), 0, Math.floor(255.0*alpha)); // Health bar colour (varies, depending on health)
+ graphics.drawRectangle(null, [hx+2, hy+2], [(width-4)*health, 10-6], colour, colour, colour, colour);
}
// Armour Bar
@@ -88,9 +109,9 @@ function drawNametag(x, y, health, armour, text, ping, alpha, distance, colour,
let hx = x-width/2;
let hy = y-10/2;
let colourB = toColour(255, 0, 0, 0); // Background colour (black)
- drawing.drawRectangle(null, [hx, hy], [width, 8], colourB, colourB, colourB, colourB);
+ graphics.drawRectangle(null, [hx, hy], [width, 8], colourB, colourB, colourB, colourB);
let colour = toColour(255, 255, 255, 255); // Armour bar colour (white)
- drawing.drawRectangle(null, [hx+2, hy+2], [(width-4)*armour, 10-6], colour, colour, colour, colour);
+ graphics.drawRectangle(null, [hx+2, hy+2], [(width-4)*armour, 10-6], colour, colour, colour, colour);
}
y -= 20;
@@ -113,7 +134,7 @@ function drawNametag(x, y, health, armour, text, ping, alpha, distance, colour,
}
}
-// -------------------------------------------------------------------------
+// ===========================================================================
function updateNametags(element) {
if(localPlayer != null) {
@@ -166,7 +187,7 @@ function updateNametags(element) {
}
}
-// -------------------------------------------------------------------------
+// ===========================================================================
function getClientFromPlayer(player) {
getClients().forEach(function(client) {
@@ -176,9 +197,9 @@ function getClientFromPlayer(player) {
});
}
-// -------------------------------------------------------------------------
+// ===========================================================================
-addEventHandler("OnDrawnHUD", function(event) {
+function processNameTagRendering(event) {
if(gta.game >= GAME_GTA_IV) {
return false;
}
@@ -188,12 +209,12 @@ addEventHandler("OnDrawnHUD", function(event) {
updateNametags(player);
}
});
-});
+}
-// -------------------------------------------------------------------------
+// ===========================================================================
function createColour(alpha, red, green, blue) {
return alpha << 24 | red << 16 | green << 8 | blue;
}
-// -------------------------------------------------------------------------
\ No newline at end of file
+// ===========================================================================
\ No newline at end of file
diff --git a/scripts/client/scoreboard.js b/scripts/client/scoreboard.js
index 4581fd15..e772a494 100644
--- a/scripts/client/scoreboard.js
+++ b/scripts/client/scoreboard.js
@@ -1,8 +1,8 @@
// ===========================================================================
// Asshat-Gaming Roleplay
// https://github.com/VortrexFTW/gtac_asshat_rp
-// Copyright (c) 2020 Asshat-Gaming (https://asshatgaming.com)
-// ---------------------------------------------------------------------------
+// Copyright (c) 2021 Asshat-Gaming (https://asshatgaming.com)
+// ===========================================================================
// FILE: scoreboard.js
// DESC: Provides scoreboard features and rendering
// TYPE: Client (JavaScript)
@@ -15,67 +15,85 @@ let pausedColour = COLOUR_RED;
let scoreboardKey = SDLK_TAB;
-// -------------------------------------------------------------------------
+// ===========================================================================
-bindEventHandler("OnResourceReady", thisResource, function(event, resource) {
- scoreBoardTitleFont = lucasFont.createDefaultFont(22.0, "Roboto", "Regular");
- scoreBoardListFont = lucasFont.createDefaultFont(12.0, "Roboto", "Light");
-});
+function initScoreBoardScript() {
+ logToConsole(LOG_DEBUG, "[Asshat.ScoreBoard]: Initializing scoreboard script ...");
+ scoreBoardTitleFont = initScoreBoardTitleFont();
+ scoreBoardListFont = initScoreBoardListFont();
+ logToConsole(LOG_DEBUG, "[Asshat.ScoreBoard]: Scoreboard script initialized!");
+}
-// -------------------------------------------------------------------------
+// ===========================================================================
-function processScoreboardRendering() {
- 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);
+function initScoreBoardTitleFont() {
+ return lucasFont.createDefaultFont(22.0, "Roboto", "Regular");
+}
- 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);
+// ===========================================================================
- 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";
+function initScoreBoardListFont() {
+ return lucasFont.createDefaultFont(12.0, "Roboto", "Light");
+}
- if(typeof playerNames[clients[i].name] != "undefined") {
- name = playerNames[clients[i].name];
- }
+// ===========================================================================
- if(typeof playerPaused[clients[i].name] != "undefined") {
- paused = playerPaused[clients[i].name];
- }
+function processScoreBoardRendering() {
+ 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(typeof playerColours[clients[i].name] != "undefined") {
- colour = playerColours[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);
- if(typeof playerPing[clients[i].name] != "undefined") {
- ping = toString(playerPing[clients[i].name]);
- }
+ 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 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);
+ if(typeof playerNames[clients[i].name] != "undefined") {
+ name = playerNames[clients[i].name];
+ }
- // 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 playerPaused[clients[i].name] != "undefined") {
+ paused = playerPaused[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 playerColours[clients[i].name] != "undefined") {
+ colour = playerColours[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 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);
+ }
+ }
}
}
}
diff --git a/scripts/client/server.js b/scripts/client/server.js
new file mode 100644
index 00000000..ed7a955f
--- /dev/null
+++ b/scripts/client/server.js
@@ -0,0 +1,245 @@
+// ===========================================================================
+// Asshat-Gaming Roleplay
+// https://github.com/VortrexFTW/gtac_asshat_rp
+// Copyright (c) 2021 Asshat-Gaming (https://asshatgaming.com)
+// ===========================================================================
+// FILE: server.js
+// DESC: Provides server communication and cross-endpoint operations
+// TYPE: Client (JavaScript)
+// ===========================================================================
+
+function initServerScript() {
+ logToConsole(LOG_DEBUG, "[Asshat.Server]: Initializing server script ...");
+ addAllNetworkHandlers();
+ logToConsole(LOG_DEBUG, "[Asshat.Server]: Server script initialized!");
+}
+
+// ===========================================================================
+
+function addAllNetworkHandlers() {
+ logToConsole(LOG_DEBUG, "[Asshat.Server]: Adding network handlers ...");
+
+ addNetworkHandler("ag.smallGameMessage", showSmallGameMessage);
+ addNetworkHandler("ag.working", setLocalPlayerWorkingState);
+ addNetworkHandler("ag.jobType", setLocalPlayerJobType);
+ addNetworkHandler("ag.passenger", enterVehicleAsPassenger);
+
+ addNetworkHandler("ag.freeze", setLocalPlayerFrozenState);
+ addNetworkHandler("ag.control", setLocalPlayerControlState);
+ addNetworkHandler("ag.fadeCamera", fadeLocalCamera);
+ addNetworkHandler("ag.removeFromVehicle", removeLocalPlayerFromVehicle);
+ addNetworkHandler("ag.clearPeds", clearLocalPlayerOwnedPeds);
+ addNetworkHandler("ag.restoreCamera", restoreLocalCamera);
+ addNetworkHandler("ag.cameraLookAt", setLocalCameraLookAt);
+ addNetworkHandler("ag.logo", setServerLogoRenderState);
+ addNetworkHandler("ag.ambience", setCityAmbienceState);
+ addNetworkHandler("ag.runCode", runClientCode);
+ addNetworkHandler("ag.clearWeapons", clearLocalPlayerWeapons);
+ addNetworkHandler("ag.giveWeapon", giveLocalPlayerWeapon);
+ addNetworkHandler("ag.position", setLocalPlayerPosition);
+ addNetworkHandler("ag.heading", setLocalPlayerHeading);
+ addNetworkHandler("ag.interior", setLocalPlayerInterior);
+
+ addNetworkHandler("ag.showJobRouteStop", showJobRouteStop);
+ addNetworkHandler("ag.snow", setSnowState);
+ addNetworkHandler("ag.health", setLocalPlayerHealth);
+ addNetworkHandler("ag.skinSelect", toggleSkinSelect);
+ addNetworkHandler("ag.hotbar", updatePlayerHotBar);
+ addNetworkHandler("ag.pedSpeech", playPedSpeech);
+ addNetworkHandler("ag.clearPedState", clearLocalPedState);
+ addNetworkHandler("ag.drunkEffect", setLocalPlayerDrunkEffect);
+ addNetworkHandler("ag.showItemActionDelay", showItemActionDelay);
+ addNetworkHandler("ag.set2DRendering", setPlayer2DRendering);
+ addNetworkHandler("ag.mouseCursor", setMouseCursorState);
+ addNetworkHandler("ag.mouseCamera", setMouseCameraState);
+ addNetworkHandler("ag.weaponDamageEnabled", setPlayerWeaponDamageEnabled);
+ addNetworkHandler("ag.weaponDamageEvent", setPlayerWeaponDamageEvent);
+ addNetworkHandler("ag.spawned", onServerSpawnedPlayer);
+ addNetworkHandler("ag.money", setLocalPlayerCash);
+
+ addNetworkHandler("ag.excludeGroundSnow", excludeModelFromGroundSnow);
+ addNetworkHandler("ag.removeWorldObject", removeWorldObject);
+
+ addNetworkHandler("ag.delKeyBind", unBindAccountKey);
+ addNetworkHandler("ag.addKeyBind", bindAccountKey);
+
+ addNetworkHandler("ag.nametag", updatePlayerNameTag);
+ addNetworkHandler("ag.ping", updatePlayerPing);
+
+ addNetworkHandler("ag.m", receiveChatBoxMessageFromServer);
+ addNetworkHandler("ag.chatScrollLines", setChatScrollLines);
+
+ addNetworkHandler("ag.radioStream", playStreamingRadio);
+ addNetworkHandler("ag.radioVolume", setStreamingRadioVolume);
+
+ addNetworkHandler("ag.veh.lights", toggleVehicleLights);
+ addNetworkHandler("ag.veh.engine", toggleVehicleEngine);
+
+ addNetworkHandler("ag.veh.sync", syncVehicleProperties);
+ addNetworkHandler("ag.civ.sync", syncCivilianProperties);
+ addNetworkHandler("ag.plr.sync", syncPlayerProperties);
+ addNetworkHandler("ag.obj.sync", syncObjectProperties);
+
+ addNetworkHandler("ag.veh.repair", repairVehicle);
+}
+
+// ===========================================================================
+
+function sendResourceReadySignalToServer() {
+ triggerNetworkEvent("ag.clientReady");
+}
+
+// ===========================================================================
+
+function sendResourceStartedSignalToServer() {
+ triggerNetworkEvent("ag.clientStarted");
+}
+
+// ===========================================================================
+
+function sendResourceStoppedSignalToServer() {
+ triggerNetworkEvent("ag.clientStopped");
+}
+
+// ===========================================================================
+
+function setPlayer2DRendering(hudState, labelState, smallGameMessageState, scoreboardState, hotBarState, itemActionDelayState) {
+ logToConsole(LOG_DEBUG, `[Asshat.Main] Updating render states (HUD: ${hudState}, Labels: ${labelState}, Bottom Text: ${smallGameMessageState}, Scoreboard: ${scoreboardState}, HotBar: ${hotBarState}, Item Action Delay: ${itemActionDelayState})`);
+ renderHUD = hudState;
+ setHUDEnabled(hudState);
+
+ renderLabels = labelState;
+ renderSmallGameMessage = smallGameMessageState;
+ renderScoreBoard = scoreboardState;
+ renderHotBar = hotBarState;
+ renderItemActionDelay = itemActionDelayState;
+}
+
+// ===========================================================================
+
+function onServerSpawnedPlayer(state) {
+ logToConsole(LOG_DEBUG, `[Asshat.Main] Setting spawned state to ${state}`);
+ isSpawned = state;
+ if(state) {
+ if(gta.game == GAME_GTA_III) {
+ gta.SET_PLAYER_NEVER_GETS_TIRED(gta.GET_PLAYER_ID(), 0);
+ gta.setGameStat(STAT_PROGRESSMADE, 9999);
+ gta.setGameStat(STAT_TOTALPROGRESSINGAME, 9999);
+ }
+
+ if(gta.game == GAME_GTA_VC) {
+ gta.SET_PLAYER_NEVER_GETS_TIRED(gta.GET_PLAYER_ID(), 0);
+ gta.setGameStat(STAT_PROGRESSMADE, 9999);
+ gta.setGameStat(STAT_TOTALPROGRESSINGAME, 9999);
+
+ gta.REQUEST_ANIMATION("bikev");
+ gta.REQUEST_ANIMATION("bikeh");
+ gta.REQUEST_ANIMATION("biked");
+ gta.REQUEST_ANIMATION("knife");
+ gta.REQUEST_ANIMATION("python");
+ gta.REQUEST_ANIMATION("shotgun");
+ gta.REQUEST_ANIMATION("buddy");
+ gta.REQUEST_ANIMATION("tec");
+ gta.REQUEST_ANIMATION("uzi");
+ gta.REQUEST_ANIMATION("rifle");
+ gta.REQUEST_ANIMATION("m60");
+ gta.REQUEST_ANIMATION("sniper");
+ gta.REQUEST_ANIMATION("grenade");
+ gta.REQUEST_ANIMATION("flame");
+ gta.REQUEST_ANIMATION("medic");
+ gta.REQUEST_ANIMATION("sunbathe");
+ gta.REQUEST_ANIMATION("playidles");
+ gta.REQUEST_ANIMATION("riot");
+ gta.REQUEST_ANIMATION("strip");
+ gta.REQUEST_ANIMATION("lance");
+ gta.REQUEST_ANIMATION("skate");
+ }
+
+ if(gta.game == GAME_GTA_SA) {
+ gta.setGameStat(STAT_WEAPONTYPE_PISTOL_SKILL, 400);
+ gta.setGameStat(STAT_WEAPONTYPE_PISTOL_SILENCED_SKILL, 400);
+ gta.setGameStat(STAT_WEAPONTYPE_DESERT_EAGLE_SKILL, 400);
+ gta.setGameStat(STAT_WEAPONTYPE_SHOTGUN_SKILL, 400);
+ gta.setGameStat(STAT_WEAPONTYPE_SAWNOFF_SHOTGUN_SKILL, 1);
+ gta.setGameStat(STAT_WEAPONTYPE_SPAS12_SHOTGUN_SKILL, 400);
+ gta.setGameStat(STAT_WEAPONTYPE_MICRO_UZI_SKILL, 400);
+ gta.setGameStat(STAT_WEAPONTYPE_MP5_SKILL, 400);
+ gta.setGameStat(STAT_WEAPONTYPE_AK47_SKILL, 400);
+ gta.setGameStat(STAT_WEAPONTYPE_M4_SKILL, 400);
+ gta.setGameStat(STAT_DRIVING_SKILL, 9999);
+ gta.setGameStat(STAT_FAT, 0);
+ gta.setGameStat(STAT_ENERGY, 9999);
+ gta.setGameStat(STAT_CYCLE_SKILL, 9999);
+ gta.setGameStat(STAT_BIKE_SKILL, 9999);
+ gta.setGameStat(STAT_GAMBLING, 9999);
+ gta.setGameStat(STAT_PROGRESS_MADE, 9999);
+ gta.setGameStat(STAT_RESPECT, 0);
+ gta.setGameStat(STAT_RESPECT_TOTAL, 0);
+ gta.setGameStat(STAT_SEX_APPEAL, 0);
+ gta.setGameStat(STAT_STAMINA, 9999);
+ gta.setGameStat(STAT_TOTAL_PROGRESS, 100);
+ gta.setGameStat(STAT_UNDERWATER_STAMINA, 9999);
+ gta.setGameStat(STAT_BODY_MUSCLE, 0);
+ }
+ }
+}
+
+// ===========================================================================
+
+function tellServerPlayerUsedKeyBind(key) {
+ triggerNetworkEvent("ag.useKeyBind", key);
+}
+
+// ===========================================================================
+
+function tellServerPlayerArrivedAtJobRouteStop() {
+ triggerNetworkEvent("ag.arrivedAtJobRouteStop");
+}
+
+// ===========================================================================
+
+function tellServerItemActionDelayComplete() {
+ triggerNetworkEvent("ag.itemActionDelayComplete");
+}
+
+// ===========================================================================
+
+function sendServerClientInfo() {
+ triggerNetworkEvent("ag.clientInfo", `${CLIENT_VERSION_MAJOR}.${CLIENT_VERSION_MINOR}.${CLIENT_VERSION_PATCH}.${CLIENT_VERSION_BUILD}`, gta.width, gta.height);
+}
+
+// ===========================================================================
+
+function sendServerNewAFKStatus(state) {
+ triggerNetworkEvent("ag.afk", state);
+}
+
+// ===========================================================================
+
+function playStreamingRadio(url, loop) {
+ //gta.forceRadioChannel(-1);
+ if(url == "") {
+ if(streamingRadio != null) {
+ streamingRadio.stop();
+ }
+ return true;
+ }
+
+ if(streamingRadio != null) {
+ streamingRadio.stop();
+ }
+
+ streamingRadio = audio.createSoundFromURL(url, loop);
+ streamingRadio.volume = 0.5;
+ streamingRadio.play();
+}
+
+// ===========================================================================
+
+function setStreamingRadioVolume(volume) {
+ if(streamingRadio != null) {
+ streamingRadio.volume = volume;
+ }
+}
+
+// ===========================================================================
\ No newline at end of file
diff --git a/scripts/client/skin-select.js b/scripts/client/skin-select.js
new file mode 100644
index 00000000..105cf305
--- /dev/null
+++ b/scripts/client/skin-select.js
@@ -0,0 +1,140 @@
+// ===========================================================================
+// Asshat-Gaming Roleplay
+// https://github.com/VortrexFTW/gtac_asshat_rp
+// Copyright (c) 2021 Asshat-Gaming (https://asshatgaming.com)
+// ===========================================================================
+// FILE: skin-select.js
+// DESC: Provides skin-selector functions and usage
+// TYPE: Client (JavaScript)
+// ===========================================================================
+
+let skinSelectMessageFontTop = null;
+let skinSelectMessageFontBottom = null;
+let skinSelectMessageTextTop = "Skin Name";
+let skinSelectMessageTextBottom = "Choose a skin using LEFT and RIGHT arrows. Use ENTER to finish or BACKSPACE to cancel.";
+let skinSelectMessageColourTop = COLOUR_YELLOW;
+let skinSelectMessageColourBottom = COLOUR_WHITE;
+
+let usingSkinSelector = false;
+let usingNewCharacterSkinSelector = false;
+let skinSelectorIndex = 0;
+
+let skinSelectPosition = null;
+let skinSelectHeading = null;
+
+let newCharacterSkinSelectPedPosition = [
+ [],
+ [139.54, -903.00, 26.16],
+ [-379.16, -535.27, 17.28],
+ [2495.03, -1685.66, 13.51],
+ [904.27, -498.00, 14.522],
+];
+
+let newCharacterSkinSelectPedHeading = [
+ [],
+ [15.0],
+ [0.0],
+ [0.01],
+ [3.127],
+];
+
+// ===========================================================================
+
+function initSkinSelectScript() {
+ logToConsole(LOG_DEBUG, "[Asshat.SkinSelect]: Initializing skin selector script ...");
+ skinSelectMessageFontTop = loadSkinSelectMessageFontTop();
+ skinSelectMessageFontBottom = loadSkinSelectMessageFontBottom();
+ logToConsole(LOG_DEBUG, "[Asshat.SkinSelect]: Skin selector script initialized!");
+}
+
+// ===========================================================================
+
+function loadSkinSelectMessageFontTop() {
+ return lucasFont.createDefaultFont(20.0, "Roboto");
+}
+
+// ===========================================================================
+
+function loadSkinSelectMessageFontBottom() {
+ return lucasFont.createDefaultFont(12.0, "Roboto", "Light");
+}
+
+// ===========================================================================
+
+function processSkinSelectKeyPress(keyCode) {
+ if(usingSkinSelector) {
+ if(keyCode == SDLK_RIGHT) {
+ if(allowedSkins[gta.game].length-1 == skinSelectorIndex) {
+ skinSelectorIndex = 0;
+ } else {
+ skinSelectorIndex++;
+ }
+ localPlayer.skin = allowedSkins[gta.game][skinSelectorIndex][0];
+ skinSelectMessageTextTop = allowedSkins[gta.game][skinSelectorIndex][1];
+ } else if(keyCode == SDLK_LEFT) {
+ if(skinSelectorIndex <= 0) {
+ skinSelectorIndex = allowedSkins[gta.game].length-1;
+ } else {
+ skinSelectorIndex--;
+ }
+ localPlayer.skin = allowedSkins[gta.game][skinSelectorIndex][0];
+ skinSelectMessageTextTop = allowedSkins[gta.game][skinSelectorIndex][1];
+ } else if(keyCode == SDLK_RETURN) {
+ triggerNetworkEvent("ag.skinSelected", skinSelectorIndex);
+ } else if(keyCode == SDLK_BACKSPACE) {
+ triggerNetworkEvent("ag.skinSelected", -1);
+ }
+ }
+}
+
+// ===========================================================================
+
+function processSkinSelectRendering() {
+ if(usingSkinSelector) {
+ if(skinSelectMessageFontTop != null && skinSelectMessageFontBottom != null) {
+ if(gta.game != GAME_GTA_VC) {
+ skinSelectMessageFontTop.render(skinSelectMessageTextTop, [0, gta.height-100], gta.width, 0.5, 0.0, skinSelectMessageFontTop.size, skinSelectMessageColourTop, true, true, false, true);
+ skinSelectMessageFontBottom.render(skinSelectMessageTextBottom, [0, gta.height-65], gta.width, 0.5, 0.0, skinSelectMessageFontBottom.size, skinSelectMessageColourBottom, true, true, false, true);
+ }
+ }
+
+ localPlayer.position = skinSelectPosition;
+ localPlayer.heading = skinSelectHeading;
+ if(gta.game == GAME_GTA_III || gta.game == GAME_GTA_VC) {
+ localPlayer.clearObjective();
+ }
+ }
+}
+
+// ===========================================================================
+
+function toggleSkinSelect(state) {
+ if(state) {
+ skinSelectorIndex = getAllowedSkinIndexBySkinId(localPlayer.skin);
+ if(localPlayer.skin != allowedSkins[gta.game][skinSelectorIndex][0]) {
+ localPlayer.skin = allowedSkins[gta.game][skinSelectorIndex][0];
+ }
+ usingSkinSelector = true;
+ let tempPosition = localPlayer.position;
+ tempPosition.z += 0.5;
+ let frontCameraPosition = getPosInFrontOfPos(tempPosition, localPlayer.heading, 3);
+ gta.setCameraLookAt(frontCameraPosition, localPlayer.position, true);
+ gui.showCursor(true, false);
+ localPlayer.invincible = true;
+ localPlayer.setProofs(true, true, true, true, true);
+ localPlayer.collisionsEnabled = false;
+ skinSelectPosition = localPlayer.position;
+ skinSelectHeading = localPlayer.heading;
+ } else {
+ usingSkinSelector = false;
+ //gta.restoreCamera(true);
+ gui.showCursor(false, true);
+ if(localPlayer) {
+ localPlayer.invincible = false;
+ localPlayer.setProofs(false, false, false, false, false);
+ localPlayer.collisionsEnabled = true;
+ }
+ }
+}
+
+// ===========================================================================
\ No newline at end of file
diff --git a/scripts/client/startup.js b/scripts/client/startup.js
new file mode 100644
index 00000000..d411110d
--- /dev/null
+++ b/scripts/client/startup.js
@@ -0,0 +1,30 @@
+// ===========================================================================
+// Asshat-Gaming Roleplay
+// https://github.com/VortrexFTW/gtac_asshat_rp
+// Copyright (c) 2021 Asshat-Gaming (https://asshatgaming.com)
+// ===========================================================================
+// FILE: startup.js
+// DESC: Provides startup/shutdown procedures
+// TYPE: Client (JavaScript)
+// ===========================================================================
+
+function initClientScripts() {
+ initGUIScript();
+ initNameTagScript();
+ initScoreBoardScript();
+ initMessagingScript();
+ initServerScript();
+ initLogoScript();
+ initLabelScript();
+ initChatBoxScript();
+ initAFKScript();
+ initKeyBindScript();
+ initEventScript();
+ initSkinSelectScript();
+}
+
+// ===========================================================================
+
+initClientScripts();
+
+// ===========================================================================
\ No newline at end of file
diff --git a/scripts/client/sync.js b/scripts/client/sync.js
index 2701b826..15d09769 100644
--- a/scripts/client/sync.js
+++ b/scripts/client/sync.js
@@ -1,65 +1,87 @@
// ===========================================================================
// Asshat-Gaming Roleplay
// https://github.com/VortrexFTW/gtac_asshat_rp
-// Copyright (c) 2020 Asshat-Gaming (https://asshatgaming.com)
-// ---------------------------------------------------------------------------
+// Copyright (c) 2021 Asshat-Gaming (https://asshatgaming.com)
+// ===========================================================================
// FILE: sync.js
// DESC: Provides some elements and data sync
// TYPE: Client (JavaScript)
// ===========================================================================
-// ---------------------------------------------------------------------------
+// ===========================================================================
-addEventHandler("onProcess", function(event, deltaTime) {
- if(localPlayer != null && isSpawned) {
- if(localPlayer.health <= 1) {
+function processSync(event, deltaTime) {
+ if(localPlayer != null) {
+ if(gta.game == GAME_GTA_IV) {
+ triggerNetworkEvent("ag.player.position", localPlayer.position);
+ triggerNetworkEvent("ag.player.heading", localPlayer.heading);
+ }
+
+ if(localPlayer.health <= 0) {
+ logToConsole(LOG_DEBUG, `Local player died`);
localPlayer.clearWeapons();
- triggerNetworkEvent("ag.player.death", localPlayer.position);
+ triggerNetworkEvent("ag.playerDeath", localPlayer.position);
}
}
-});
+}
-// ---------------------------------------------------------------------------
+// ===========================================================================
-addNetworkHandler("ag.veh.engine", function(vehicle, state) {
+function toggleVehicleEngine(vehicle, state) {
vehicle.engine = state;
-});
+}
-// ---------------------------------------------------------------------------
+// ===========================================================================
-addNetworkHandler("ag.veh.lights", function(vehicle, state) {
- vehicle.lights = state;
-});
+function toggleVehicleLights(vehicle, state) {
+ getElementFromId(vehicle).lights = state;
+}
-// ---------------------------------------------------------------------------
+// ===========================================================================
-addNetworkHandler("ag.veh.repair", function(syncId) {
+function repairVehicle(syncId) {
getVehicleFromSyncId(syncId).fix();
-});
+}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function syncVehicleProperties(vehicle) {
- //if(doesEntityDataExist(vehicle, "ag.lights")) {
- // let lights = getEntityData(vehicle, "ag.lights");
- // if(lights != vehicle.lights) {
- // vehicle.lights = lights;
- // }
- //}
+ if(vehicle != null) {
+ syncVehicleProperties(vehicle);
+ }
+}
- //if(doesEntityDataExist(vehicle, "ag.engine")) {
- // let engine = getEntityData(vehicle, "ag.engine");
- // if(engine != vehicle.engine) {
- // vehicle.engine = engine;
- // }
- //}
+// ===========================================================================
- //if(doesEntityDataExist(vehicle, "ag.siren")) {
- // let siren = getEntityData(vehicle, "ag.siren");
- // if(siren != vehicle.siren) {
- // vehicle.siren = siren;
- // }
- //}
+function syncCivilianProperties(civilian) {
+ if(civilian != null) {
+ syncCivilianProperties(civilian);
+ }
+}
+
+// ===========================================================================
+
+function syncPlayerProperties(player) {
+ if(player != null) {
+ syncPlayerProperties(player);
+ }
+}
+
+// ===========================================================================
+
+function syncObjectProperties(object) {
+ if(object != null) {
+ syncObjectProperties(object);
+ }
+}
+
+// ===========================================================================
+
+function syncVehicleProperties(vehicle) {
+ if(doesEntityDataExist(vehicle, "ag.lights")) {
+ let lightStatus = getEntityData(vehicle, "ag.lights");
+ vehicle.lights = lightStatus;
+ }
if(doesEntityDataExist(vehicle, "ag.panelStatus")) {
let panelsStatus = getEntityData(vehicle, "ag.panelStatus");
@@ -82,64 +104,269 @@ function syncVehicleProperties(vehicle) {
}
}
- if(doesEntityDataExist(vehicle, "ag.suspensionHeight")) {
- let suspensionHeight = getEntityData(vehicle, "ag.suspensionHeight");
- vehicle.setSuspensionHeight(suspensionHeight);
- }
-}
-addNetworkHandler("ag.veh.sync", function(event, vehicle) {
- syncVehicleProperties(vehicle);
-});
+ //if(doesEntityDataExist(vehicle, "ag.suspensionHeight")) {
+ // let suspensionHeight = getEntityData(vehicle, "ag.suspensionHeight");
+ // vehicle.setSuspensionHeight(suspensionHeight);
+ //}
-// ---------------------------------------------------------------------------
+ if(getGame() == GAME_GTA_SA) {
+ if(doesEntityDataExist(vehicle, "ag.upgrades")) {
+ let upgrades = getEntityData(vehicle, "ag.upgrades");
+ for(let i in upgrades) {
+ vehicle.addUpgrade(upgrades[i]);
+ }
+ }
+ }
+
+ if(getGame() == GAME_GTA_SA || getGame() == GAME_GTA_IV) {
+ if(doesEntityDataExist(vehicle, "ag.livery")) {
+ let livery = getEntityData(vehicle, "ag.livery");
+ if(getGame() == GAME_GTA_SA) {
+ vehicle.setPaintJob(livery);
+ } else if(getGame() == GAME_GTA_IV) {
+ vehicle.livery = livery;
+ }
+ }
+ }
+
+ //gta.REMOVE_UPSIDEDOWN_CAR_CHECK(gta.GET_VEHICLE_ID(vehicle));
+}
+
+// ===========================================================================
function syncCivilianProperties(civilian) {
- if(doesEntityDataExist(civilian, "ag.scale")) {
- let scaleFactor = getEntityData(civilian, "ag.scale");
- let tempMatrix = civilian.matrix;
- tempMatrix.setScale(toVector3(scaleFactor.x, scaleFactor.y, scaleFactor.z));
- let tempPosition = civilian.position;
- civilian.matrix = tempMatrix;
- tempPosition.z += scaleFactor.z;
- civilian.position = tempPosition;
+ if(getGame() == GAME_GTA_III) {
+ if(doesEntityDataExist(civilian, "ag.scale")) {
+ let scaleFactor = getEntityData(civilian, "ag.scale");
+ let tempMatrix = civilian.matrix;
+ tempMatrix.setScale(toVector3(scaleFactor.x, scaleFactor.y, scaleFactor.z));
+ let tempPosition = civilian.position;
+ civilian.matrix = tempMatrix;
+ tempPosition.z += scaleFactor.z;
+ civilian.position = tempPosition;
+ }
+ }
+
+ if(getGame() == GAME_GTA_SA) {
+ if(doesEntityDataExist(civilian, "ag.fightStyle")) {
+ let fightStyle = getEntityData(civilian, "ag.fightStyle");
+ civilian.setFightStyle(fightStyle[0], fightStyle[1]);
+ }
+ }
+
+ if(getGame() == GAME_GTA_III) {
+ if(doesEntityDataExist(civilian, "ag.walkStyle")) {
+ let walkStyle = getEntityData(civilian, "ag.walkStyle");
+ civilian.walkStyle = walkStyle;
+ }
+ }
+
+ if(getGame() == GAME_GTA_IV) {
+ if(doesEntityDataExist(civilian, "ag.bodyPropHair")) {
+ let bodyPropHair = getEntityData(civilian, "ag.bodyPropHair");
+ civilian.changeBodyProp(0, bodyPropHair[0], bodyPropHair[1]);
+ }
+
+ if(doesEntityDataExist(civilian, "ag.bodyPropHead")) {
+ let bodyPropHead = getEntityData(civilian, "ag.bodyPropHead");
+ civilian.changeBodyProp(1, bodyPropHead[0], bodyPropHead[1]);
+ }
+
+ if(doesEntityDataExist(civilian, "ag.bodyPropEyes")) {
+ let bodyPropEyes = getEntityData(civilian, "ag.bodyPropEyes");
+ civilian.changeBodyProp(1, bodyPropEyes[0], bodyPropEyes[1]);
+ }
+
+ if(doesEntityDataExist(civilian, "ag.bodyPropLeftHand")) {
+ let bodyPropLeftHand = getEntityData(civilian, "ag.bodyPropLeftHand");
+ civilian.changeBodyProp(1, bodyPropLeftHand[0], bodyPropLeftHand[1]);
+ }
+
+ if(doesEntityDataExist(civilian, "ag.bodyPropRightHand")) {
+ let bodyPropRightHand = getEntityData(civilian, "ag.bodyPropRightHand");
+ civilian.changeBodyProp(1, bodyPropRightHand[0], bodyPropRightHand[1]);
+ }
+
+ if(doesEntityDataExist(civilian, "ag.bodyPropLeftWrist")) {
+ let bodyPropLeftWrist = getEntityData(civilian, "ag.bodyPropLeftWrist");
+ civilian.changeBodyProp(1, bodyPropLeftWrist[0], bodyPropLeftWrist[1]);
+ }
+
+ if(doesEntityDataExist(civilian, "ag.bodyPropRightWrist")) {
+ let bodyPropRightWrist = getEntityData(civilian, "ag.bodyPropRightWrist");
+ civilian.changeBodyProp(1, bodyPropRightWrist[0], bodyPropRightWrist[1]);
+ }
+
+ if(doesEntityDataExist(civilian, "ag.bodyPropRightWrist")) {
+ let bodyPropRightWrist = getEntityData(civilian, "ag.bodyPropRightWrist");
+ civilian.changeBodyProp(1, bodyPropRightWrist[0], bodyPropRightWrist[1]);
+ }
+
+ if(doesEntityDataExist(civilian, "ag.bodyPropHip")) {
+ let bodyPropHip = getEntityData(civilian, "ag.bodyPropHip");
+ civilian.changeBodyProp(1, bodyPropHip[0], bodyPropHip[1]);
+ }
+
+ if(doesEntityDataExist(civilian, "ag.bodyPropLeftFoot")) {
+ let bodyPropLeftFoot = getEntityData(civilian, "ag.bodyPropLeftFoot");
+ civilian.changeBodyProp(1, bodyPropLeftFoot[0], bodyPropLeftFoot[1]);
+ }
+
+ if(doesEntityDataExist(civilian, "ag.bodyPropRightFoot")) {
+ let bodyPropRightFoot = getEntityData(civilian, "ag.bodyPropRightFoot");
+ civilian.changeBodyProp(1, bodyPropRightFoot[0], bodyPropRightFoot[1]);
+ }
}
}
-addNetworkHandler("ag.civ.sync", function(event, civilian) {
- //syncCivilianProperties(civilian);
-});
-// ---------------------------------------------------------------------------
+// ===========================================================================
function syncPlayerProperties(player) {
- if(doesEntityDataExist(player, "ag.scale")) {
- let scaleFactor = getEntityData(player, "ag.scale");
- let tempMatrix = player.matrix;
- tempMatrix.setScale(toVector3(scaleFactor.x, scaleFactor.y, scaleFactor.z));
- let tempPosition = player.position;
- player.matrix = tempMatrix;
- tempPosition.z += scaleFactor.z;
- player.position = tempPosition;
+ if(getGame() == GAME_GTA_III) {
+ if(doesEntityDataExist(player, "ag.scale")) {
+ let scaleFactor = getEntityData(player, "ag.scale");
+ let tempMatrix = player.matrix;
+ tempMatrix.setScale(toVector3(scaleFactor.x, scaleFactor.y, scaleFactor.z));
+ let tempPosition = player.position;
+ player.matrix = tempMatrix;
+ tempPosition.z += scaleFactor.z;
+ player.position = tempPosition;
+ }
+ }
+
+ if(getGame() == GAME_GTA_SA) {
+ if(doesEntityDataExist(player, "ag.fightStyle")) {
+ let fightStyle = getEntityData(player, "ag.fightStyle");
+ player.fightStyle = fightStyle;
+ }
+ }
+
+ //if(getGame() == GAME_GTA_SA) {
+ // if(doesEntityDataExist(player, "ag.walkStyle")) {
+ // let walkStyle = getEntityData(player, "ag.walkStyle");
+ // player.walkStyle = walkStyle;
+ // }
+ //}
+
+ if(getGame() == GAME_GTA_IV) {
+ if(doesEntityDataExist(player, "ag.bodyPartHair")) {
+ let bodyPartHead = getEntityData(player, "ag.bodyPartHair");
+ player.changeBodyPart(0, bodyPartHead[0], bodyPartHair[1]);
+ }
+
+ if(doesEntityDataExist(player, "ag.bodyPartHead")) {
+ let bodyPartHead = getEntityData(player, "ag.bodyPartHead");
+ player.changeBodyPart(1, bodyPartHead[0], bodyPartHead[1]);
+ }
+
+ if(doesEntityDataExist(player, "ag.bodyPartUpper")) {
+ let bodyPartUpper = getEntityData(player, "ag.bodyPartUpper");
+ player.changeBodyPart(1, bodyPartUpper[0], bodyPartUpper[1]);
+ }
+
+ if(doesEntityDataExist(player, "ag.bodyPartLower")) {
+ let bodyPartLower = getEntityData(player, "ag.bodyPartLower");
+ player.changeBodyPart(1, bodyPartLower[0], bodyPartLower[1]);
+ }
+ }
+
+ if(getGame() == GAME_GTA_IV) {
+ if(doesEntityDataExist(player, "ag.bodyPropHair")) {
+ let bodyPropHair = getEntityData(player, "ag.bodyPropHair");
+ player.changeBodyProp(0, bodyPropHair[0], bodyPropHair[1]);
+ }
+
+ if(doesEntityDataExist(player, "ag.bodyPropHead")) {
+ let bodyPropHead = getEntityData(player, "ag.bodyPropHead");
+ player.changeBodyProp(1, bodyPropHead[0], bodyPropHead[1]);
+ }
+
+ if(doesEntityDataExist(player, "ag.bodyPropEyes")) {
+ let bodyPropEyes = getEntityData(player, "ag.bodyPropEyes");
+ player.changeBodyProp(1, bodyPropEyes[0], bodyPropEyes[1]);
+ }
+
+ if(doesEntityDataExist(player, "ag.bodyPropLeftHand")) {
+ let bodyPropLeftHand = getEntityData(player, "ag.bodyPropLeftHand");
+ player.changeBodyProp(1, bodyPropLeftHand[0], bodyPropLeftHand[1]);
+ }
+
+ if(doesEntityDataExist(player, "ag.bodyPropRightHand")) {
+ let bodyPropRightHand = getEntityData(player, "ag.bodyPropRightHand");
+ player.changeBodyProp(1, bodyPropRightHand[0], bodyPropRightHand[1]);
+ }
+
+ if(doesEntityDataExist(player, "ag.bodyPropLeftWrist")) {
+ let bodyPropLeftWrist = getEntityData(player, "ag.bodyPropLeftWrist");
+ player.changeBodyProp(1, bodyPropLeftWrist[0], bodyPropLeftWrist[1]);
+ }
+
+ if(doesEntityDataExist(player, "ag.bodyPropRightWrist")) {
+ let bodyPropRightWrist = getEntityData(player, "ag.bodyPropRightWrist");
+ player.changeBodyProp(1, bodyPropRightWrist[0], bodyPropRightWrist[1]);
+ }
+
+ if(doesEntityDataExist(player, "ag.bodyPropRightWrist")) {
+ let bodyPropRightWrist = getEntityData(player, "ag.bodyPropRightWrist");
+ player.changeBodyProp(1, bodyPropRightWrist[0], bodyPropRightWrist[1]);
+ }
+
+ if(doesEntityDataExist(player, "ag.bodyPropHip")) {
+ let bodyPropHip = getEntityData(player, "ag.bodyPropHip");
+ player.changeBodyProp(1, bodyPropHip[0], bodyPropHip[1]);
+ }
+
+ if(doesEntityDataExist(player, "ag.bodyPropLeftFoot")) {
+ let bodyPropLeftFoot = getEntityData(player, "ag.bodyPropLeftFoot");
+ player.changeBodyProp(1, bodyPropLeftFoot[0], bodyPropLeftFoot[1]);
+ }
+
+ if(doesEntityDataExist(player, "ag.bodyPropRightFoot")) {
+ let bodyPropRightFoot = getEntityData(player, "ag.bodyPropRightFoot");
+ player.changeBodyProp(1, bodyPropRightFoot[0], bodyPropRightFoot[1]);
+ }
}
}
-addNetworkHandler("ag.player.sync", function(event, player) {
- syncPlayerProperties(player);
-});
-// ---------------------------------------------------------------------------
+// ===========================================================================
function syncObjectProperties(object) {
- if(doesEntityDataExist(object, "ag.scale")) {
- let scaleFactor = getEntityData(object, "ag.scale");
- let tempMatrix = object.matrix;
- tempMatrix.setScale(toVector3(scaleFactor.x, scaleFactor.y, scaleFactor.z));
- let tempPosition = object.position;
- object.matrix = tempMatrix;
- tempPosition.z += scaleFactor.z;
- object.position = tempPosition;
+ if(getGame() == GAME_GTA_III) {
+ if(doesEntityDataExist(object, "ag.scale")) {
+ let scaleFactor = getEntityData(object, "ag.scale");
+ let tempMatrix = object.matrix;
+ tempMatrix.setScale(toVector3(scaleFactor.x, scaleFactor.y, scaleFactor.z));
+ let tempPosition = object.position;
+ object.matrix = tempMatrix;
+ tempPosition.z += scaleFactor.z;
+ object.position = tempPosition;
+ }
}
}
-addNetworkHandler("ag.obj.sync", function(event, object) {
- //syncObjectProperties(object);
-});
-// ---------------------------------------------------------------------------
\ No newline at end of file
+// ===========================================================================
+
+function syncElementProperties(element) {
+ switch(element.type) {
+ case ELEMENT_VEHICLE:
+ syncVehicleProperties(element);
+ break;
+
+ case ELEMENT_CIVILIAN:
+ syncCivilianProperties(element);
+ break;
+
+ case ELEMENT_PLAYER:
+ syncPlayerProperties(element);
+ break;
+
+ case ELEMENT_OBJECT:
+ syncObjectProperties(element);
+ break;
+
+ default:
+ break;
+ }
+}
+
+// ===========================================================================
\ No newline at end of file
diff --git a/scripts/client/utilities.js b/scripts/client/utilities.js
new file mode 100644
index 00000000..866a40f8
--- /dev/null
+++ b/scripts/client/utilities.js
@@ -0,0 +1,629 @@
+// ===========================================================================
+// Asshat-Gaming Roleplay
+// https://github.com/VortrexFTW/gtac_asshat_rp
+// Copyright (c) 2021 Asshat-Gaming (https://asshatgaming.com)
+// ===========================================================================
+// FILE: utilities.js
+// DESC: Provides util functions and arrays with data
+// TYPE: Client (JavaScript)
+// ===========================================================================
+
+let weaponSlots = [
+ false,
+ [
+ 0,
+ 1,
+ 2,
+ 3,
+ 4,
+ 5,
+ 6,
+ 7,
+ 8,
+ 9,
+ 10,
+ 11
+ ],
+ [
+ 0,
+ 0,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 2,
+ 2,
+ 2,
+ 2,
+ 2,
+ 3,
+ 3,
+ 4,
+ 4,
+ 4,
+ 5,
+ 5,
+ 5,
+ 5,
+ 6,
+ 6,
+ 8,
+ 8,
+ 7,
+ 7,
+ 7,
+ 7,
+ 9,
+ -1,
+ 9,
+ ],
+ [
+ 0,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 8,
+ 8,
+ 8,
+ -1,
+ -1,
+ -1,
+ 2,
+ 2,
+ 2,
+ 3,
+ 3,
+ 3,
+ 4,
+ 4,
+ 5,
+ 5,
+ 4,
+ 6,
+ 6,
+ 7,
+ 7,
+ 7,
+ 7,
+ 8,
+ 12,
+ 9,
+ 9,
+ 9,
+ 9,
+ 9,
+ 11,
+ 9,
+ 9,
+ 9,
+ ],
+];
+
+function openAllGarages() {
+ switch(gta.game) {
+ case GAME_GTA_III:
+ for(let i=0;i<=26;i++) {
+ openGarage(i);
+ //gta.NO_SPECIAL_CAMERA_FOR_THIS_GARAGE(i);
+ }
+ break;
+
+ case GAME_GTA_VC:
+ for(let i=0;i<=32;i++) {
+ openGarage(i);
+ //gta.NO_SPECIAL_CAMERA_FOR_THIS_GARAGE(i);
+ }
+ break;
+
+ case GAME_GTA_SA:
+ for(let i=0;i<=44;i++) {
+ openGarage(i);
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+// ===========================================================================
+
+function closeAllGarages() {
+ switch(gta.game) {
+ case GAME_GTA_III:
+ for(let i=0;i<=26;i++) {
+ closeGarage(i);
+ //gta.NO_SPECIAL_CAMERA_FOR_THIS_GARAGE(i);
+ }
+ break;
+
+ case GAME_GTA_VC:
+ for(let i=0;i<=32;i++) {
+ closeGarage(i);
+ //gta.NO_SPECIAL_CAMERA_FOR_THIS_GARAGE(i);
+ }
+ break;
+
+ case GAME_GTA_SA:
+ for(let i=0;i<=44;i++) {
+ closeGarage(i);
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+// ===========================================================================
+
+function setLocalPlayerFrozenState(state) {
+ logToConsole(LOG_DEBUG, `[Asshat.Utilities] Setting frozen state to ${state}`);
+ gui.showCursor(state, !state);
+}
+
+// ===========================================================================
+
+function setLocalPlayerControlState(controlState, cursorState = false) {
+ logToConsole(LOG_DEBUG, `[Asshat.Utilities] Setting control state to ${controlState} (Cursor: ${cursorState})`);
+ controlsEnabled = controlState;
+ localPlayer.invincible = true;
+ localPlayer.collisionsEnabled = controlState;
+ localPlayer.invincible = false;
+}
+
+// ===========================================================================
+
+function fadeLocalCamera(state, time) {
+ logToConsole(LOG_DEBUG, `[Asshat.Utilities] Fading camera ${(state)?"in":"out"} for ${time} seconds`);
+ gta.fadeCamera(state, time);
+}
+
+// ===========================================================================
+
+function removeLocalPlayerFromVehicle() {
+ localPlayer.removeFromVehicle();
+}
+
+// ===========================================================================
+
+function restoreLocalCamera() {
+ logToConsole(LOG_DEBUG, `[Asshat.Utilities] Camera restored`);
+ gta.restoreCamera(true);
+};
+
+// ===========================================================================
+
+function clearLocalPlayerOwnedPeds() {
+ logToConsole(LOG_DEBUG, `[Asshat.Utilities] Clearing all self-owned peds ...`);
+ clearSelfOwnedPeds();
+ logToConsole(LOG_DEBUG, `[Asshat.Utilities] All self-owned peds cleared`);
+};
+
+// ===========================================================================
+
+function setLocalCameraLookAt(cameraPosition, cameraLookAt) {
+ logToConsole(LOG_DEBUG, `[Asshat.Utilities] Set camera to look at [${cameraLookAt.x}, ${cameraLookAt.y}, ${cameraLookAt.z}] from [${cameraPosition.x}, ${cameraPosition.y}, ${cameraPosition.z}]`);
+ gta.setCameraLookAt(cameraPosition, cameraLookAt, true);
+}
+
+// ===========================================================================
+
+function setCityAmbienceState(state) {
+ logToConsole(LOG_DEBUG, `[Asshat.Utilities] Ambient civilians and traffic ${(state) ? "enabled" : "disabled"}`);
+ gta.setTrafficEnabled(state);
+ gta.setGenerateCarsAroundCamera(state);
+ if(gta.game != GAME_GTA_SA) {
+ gta.setCiviliansEnabled(state);
+ }
+ clearSelfOwnedPeds();
+}
+
+// ===========================================================================
+
+function runClientCode(code, returnTo) {
+ let returnValue = "Nothing";
+ try {
+ returnValue = eval("(" + code + ")");
+ } catch(error) {
+ triggerNetworkEvent("ag.runCodeFail", returnTo, code);
+ return false;
+ }
+ triggerNetworkEvent("ag.runCodeSuccess", returnTo, code, returnValue);
+}
+
+// ===========================================================================
+
+function enterVehicleAsPassenger() {
+ if(localPlayer.vehicle == null) {
+ let tempVehicle = getClosestVehicle(localPlayer.position);
+ if(tempVehicle != null) {
+ localPlayer.enterVehicle(tempVehicle, false);
+ }
+ }
+}
+
+// ===========================================================================
+
+function giveLocalPlayerWeapon(weaponId, ammo, active) {
+ logToConsole(LOG_DEBUG, `[Asshat.Utilities] Giving weapon ${weaponId} with ${ammo} ammo`);
+ localPlayer.giveWeapon(weaponId, ammo, active);
+ forceWeaponAmmo = localPlayer.getWeaponAmmunition(getWeaponSlot(weaponId));
+ forceWeaponClipAmmo = localPlayer.getWeaponClipAmmunition(getWeaponSlot(weaponId));
+ forceWeapon = weaponId;
+}
+
+// ===========================================================================
+
+function giveLocalPlayerWeapon(weaponId, ammo, active) {
+ logToConsole(LOG_DEBUG, `[Asshat.Utilities] Giving weapon ${weaponId} with ${ammo} ammo`);
+ localPlayer.giveWeapon(weaponId, ammo, active);
+ forceWeaponAmmo = localPlayer.getWeaponAmmunition(getWeaponSlot(weaponId));
+ forceWeaponClipAmmo = localPlayer.getWeaponClipAmmunition(getWeaponSlot(weaponId));
+ forceWeapon = weaponId;
+}
+
+// ===========================================================================
+
+function clearLocalPlayerWeapons() {
+ logToConsole(LOG_DEBUG, `[Asshat.Utilities] Clearing weapons`);
+ localPlayer.clearWeapons();
+ forceWeapon = 0;
+ forceWeaponAmmo = 0;
+ forceWeaponClipAmmo = 0;
+}
+
+// ===========================================================================
+
+function getClosestVehicle(pos) {
+ return getVehicles().reduce((i, j) => (i.position.distance(pos) < j.position.distance(pos)) ? i : j);
+}
+
+// ===========================================================================
+
+function setLocalPlayerPosition(position) {
+ logToConsole(LOG_DEBUG, `[Asshat.Utilities] Setting position to ${position.x}, ${position.y}, ${position.z}`);
+ localPlayer.velocity = toVector3(0.0, 0.0, 0.0);
+ localPlayer.position = position;
+}
+
+// ===========================================================================
+
+function setLocalPlayerHeading(heading) {
+ logToConsole(LOG_DEBUG, `[Asshat.Utilities] Setting heading to ${heading}`);
+ localPlayer.heading = heading;
+}
+
+// ===========================================================================
+
+function setLocalPlayerInterior(interior) {
+ logToConsole(LOG_DEBUG, `[Asshat.Utilities] Setting interior to ${interior}`);
+ localPlayer.interior = interior;
+ gta.cameraInterior = interior;
+}
+
+// ===========================================================================
+
+function setSnowState(fallingSnow, groundSnow) {
+ logToConsole(LOG_DEBUG, `[Asshat.Utilities] Setting falling snow to ${fallingSnow} and ground snow to ${groundSnow}`);
+ if(!isNull(snowing)) {
+ snowing = fallingSnow;
+ forceSnowing(groundSnow);
+ }
+}
+
+// ===========================================================================
+
+function setLocalPlayerHealth(health) {
+ localPlayer.health = health;
+}
+
+// ===========================================================================
+
+function isSnowEnabled() {
+ return (typeof snowing != "undefined");
+}
+
+// ===========================================================================
+
+function playPedSpeech(pedName, speechId) {
+ logToConsole(LOG_DEBUG, `[Asshat.Utilities] Making ${pedName}'s ped talk (${speechId})`);
+ gta.SET_CHAR_SAY(int, int);
+}
+
+// ===========================================================================
+
+function clearLocalPedState() {
+ logToConsole(LOG_DEBUG, `[Asshat.Utilities] Clearing local ped state`);
+ localPlayer.clearObjective();
+}
+
+// ===========================================================================
+
+function getWeaponSlot(weaponId) {
+ return weaponSlots[gta.game][weaponId];
+}
+
+// ===========================================================================
+
+function setLocalPlayerDrunkEffect(amount, duration) {
+ logToConsole(LOG_DEBUG, `[Asshat.Utilities] Drunk effect set to ${amount} for ${duration}ms`);
+ drunkEffectAmount = 0;
+ drunkEffectDurationTimer = setInterval(function() {
+ drunkEffectAmount = drunkEffectAmount;
+ if(drunkEffectAmount > 0) {
+ gta.SET_MOTION_BLUR(drunkEffectAmount);
+ } else {
+ clearInterval(drunkEffectDurationTimer);
+ drunkEffectDurationTimer = null;
+ }
+ }, 1000);
+}
+
+// ===========================================================================
+
+function getLocalPlayerVehicleSeat() {
+ for(let i = 0 ; i <= 4 ; i++) {
+ if(localPlayer.vehicle.getOccupant(i) == localPlayer) {
+ return i;
+ }
+ }
+}
+
+// ===========================================================================
+
+function clearSelfOwnedPeds() {
+ logToConsole(LOG_DEBUG, `Clearing self-owned peds`);
+ getElementsByType(ELEMENT_CIVILIAN).forEach(function(ped) {
+ if(ped.isOwner) {
+ destroyElement(ped);
+ }
+ });
+}
+
+// ===========================================================================
+
+function setMouseCameraState(state) {
+ logToConsole(LOG_DEBUG, `[Asshat.Utilities] ${(state)?"Enabled":"Disabled"} mouse camera`);
+ mouseCameraEnabled = !mouseCameraEnabled;
+ SetStandardControlsEnabled(!mouseCameraEnabled);
+}
+
+// ===========================================================================
+
+function setMouseCursorState(state) {
+ logToConsole(LOG_DEBUG, `[Asshat.Utilities] ${(state)?"Enabled":"Disabled"} mouse cursor`);
+ gui.showCursor(state, !state);
+}
+
+// ===========================================================================
+
+function setPlayerWeaponDamageEvent(clientName, eventType) {
+ logToConsole(LOG_DEBUG, `[Asshat.Utilities] Set ${clientName} damage event type to ${eventType}`);
+ weaponDamageEvent[clientName] = eventType;
+}
+
+// ===========================================================================
+
+function setPlayerWeaponDamageEnabled(clientName, state) {
+ logToConsole(LOG_DEBUG, `[Asshat.Utilities] ${(state)?"Enabled":"Disabled"} damage from ${clientName}`);
+ weaponDamageEnabled[clientName] = state;
+}
+
+// ===========================================================================
+
+function setLocalPlayerCash(amount) {
+ logToConsole(LOG_DEBUG, `[Asshat.Utilities] Setting local player money`);
+ localPlayer.money = amount;
+}
+
+// ===========================================================================
+
+function removeWorldObject(model, position, range) {
+ logToConsole(LOG_DEBUG, `[Asshat.Utilities] Removing world object ${model} at X: ${position.x}, Y: ${position.x}, Z: ${position.x} with range of ${range}`);
+ gta.removeWorldObject(model, position, range);
+}
+
+// ===========================================================================
+
+function excludeModelFromGroundSnow(model) {
+ logToConsole(LOG_DEBUG, `[Asshat.Utilities] Disabling ground snow for object model ${model}`);
+ groundSnow.excludeModel(model);
+}
+
+// ===========================================================================
+
+function destroyAutoCreatedPickups() {
+ getElementsByType(ELEMENT_PICKUP).forEach(function(pickup) {
+ if(pickup.isOwner) {
+ destroyElement(pickup);
+ }
+ });
+}
+
+// ===========================================================================
+
+function processLocalPlayerControlState() {
+ if(localPlayer == null) {
+ return false;
+ }
+
+ if(isSpawned) {
+ return false;
+ }
+
+ if(!controlsEnabled) {
+ clearLocalPedState();
+ }
+}
+
+// ===========================================================================
+
+function clearLocalPlayerWantedLevel() {
+ if(localPlayer == null) {
+ return false;
+ }
+
+ if(isSpawned) {
+ return false;
+ }
+
+ localPlayer.wantedLevel = 0;
+}
+
+// ===========================================================================
+
+function processLocalPlayerVehicleControlState() {
+ let position = getLocalPlayerPosition();
+
+ if(inVehicle && localPlayer.vehicle != null) {
+ if(!localPlayer.vehicle.engine) {
+ 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 {
+ if(parkedVehiclePosition) {
+ parkedVehiclePosition = false;
+ parkedVehicleHeading = false;
+ }
+ }
+ }
+}
+
+// ===========================================================================
+
+function processLocalPlayerSphereEntryExitHandling() {
+ let position = getLocalPlayerPosition();
+
+ getElementsByType(ELEMENT_MARKER).forEach(function(sphere) {
+ if(getDistance(position, sphere.position) <= sphere.radius) {
+ if(!inSphere) {
+ inSphere = sphere;
+ triggerEvent("OnLocalPlayerEnterSphere", null, sphere);
+ }
+ } else {
+ if(inSphere) {
+ inSphere = false;
+ triggerEvent("OnLocalPlayerExitSphere", null, sphere);
+ }
+ }
+ });
+}
+
+// ===========================================================================
+
+function processJobRouteSphere() {
+ if(gta.game == GAME_GTA_SA) {
+ let position = getLocalPlayerPosition();
+ if(jobRouteStopSphere != null) {
+ if(getDistance(position, jobRouteStopSphere.position) <= 2.0) {
+ enteredJobRouteSphere();
+ }
+ }
+ }
+}
+
+// ===========================================================================
+
+function forceLocalPlayerEquippedWeaponItem() {
+ if(forceWeapon != 0) {
+ if(localPlayer.weapon != forceWeapon) {
+ localPlayer.weapon = forceWeapon;
+ localPlayer.setWeaponClipAmmunition(getWeaponSlot(forceWeapon), forceWeaponClipAmmo);
+ localPlayer.setWeaponAmmunition(getWeaponSlot(forceWeapon), forceWeaponAmmo);
+ } else {
+ forceWeaponClipAmmo = localPlayer.getWeaponClipAmmunition(getWeaponSlot(forceWeapon));
+ forceWeaponAmmo = localPlayer.getWeaponAmmunition(getWeaponSlot(forceWeapon));
+ }
+ } else {
+ if(localPlayer.weapon > 0) {
+ localPlayer.clearWeapons();
+ }
+ }
+}
+
+// ===========================================================================
+
+function getLocalPlayerPosition() {
+ let position = localPlayer.position;
+ if(localPlayer.vehicle) {
+ position = localPlayer.vehicle.position;
+ }
+
+ return position;
+}
+
+// ===========================================================================
+
+function processLocalPlayerVehicleEntryExitHandling() {
+ if(localPlayer.vehicle) {
+ if(!inVehicle) {
+ inVehicle = localPlayer.vehicle;
+ inVehicleSeat = getLocalPlayerVehicleSeat();
+ triggerEvent("OnLocalPlayerEnteredVehicle", inVehicle, inVehicleSeat);
+ }
+ } else {
+ if(inVehicle) {
+ triggerEvent("OnLocalPlayerExitedVehicle", inVehicle, inVehicleSeat);
+ inVehicle = false;
+ inVehicleSeat = false;
+ }
+ }
+}
+
+// ===========================================================================
+
+function getVehicleForNetworkEvent(vehicleArg) {
+ // Soon this will also be used to get the IV vehicle via it's ID
+ return vehicleArg;
+}
+
+// ===========================================================================
+
+function getPosInFrontOfPos(pos, angle, distance) {
+ let x = (pos.x+((Math.cos(angle+(Math.PI/2)))*distance));
+ let y = (pos.y+((Math.sin(angle+(Math.PI/2)))*distance));
+ let z = pos.z;
+
+ return toVector3(x, y, z);
+}
+
+// ===========================================================================
+
+function getAllowedSkinIndexBySkinId(skinId) {
+ for(let i in allowedSkins[gta.game]) {
+ if(skinId == allowedSkins[gta.game][i][0]) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+// ===========================================================================
+
+function processWantedLevelReset() {
+ localPlayer.wantedLevel = 0;
+}
+
+// ===========================================================================
\ No newline at end of file
diff --git a/scripts/jsconfig.json b/scripts/jsconfig.json
new file mode 100644
index 00000000..51bb73e6
--- /dev/null
+++ b/scripts/jsconfig.json
@@ -0,0 +1,12 @@
+{
+ "compilerOptions": {
+ "module": "commonjs",
+ "target": "es2020",
+ "moduleResolution": "classic"
+ },
+ "include": [
+ "server/*",
+ "client/*",
+ "third-party/*"
+ ]
+}
\ No newline at end of file
diff --git a/scripts/server/accent.js b/scripts/server/accent.js
index 962b1ea1..4e60288f 100644
--- a/scripts/server/accent.js
+++ b/scripts/server/accent.js
@@ -2,41 +2,14 @@
// Asshat-Gaming Roleplay
// https://github.com/VortrexFTW/gtac_asshat_rp
// Copyright (c) 2021 Asshat-Gaming (https://asshatgaming.com)
-// ---------------------------------------------------------------------------
+// ===========================================================================
// FILE: accent.js
// DESC: Provides accent functions and usage
// TYPE: Server (JavaScript)
// ===========================================================================
-let accents = [
- "English",
- "French",
- "Russian",
- "Scottish",
- "Irish",
- "Spanish",
- "Southern American",
- "Italian",
- "Australian",
- "Jamaican",
- "Israeli",
- "Dutch",
- "Brazilian",
- "Portuguese",
- "German",
- "Canadian",
- "Chinese",
- "Japanese",
- "Turkish",
- "Korean",
- "Estonian",
- "Sicilian",
-];
-
-// ---------------------------------------------------------------------------
-
function getPlayerAccentText(client) {
return getPlayerCurrentSubAccount(client).accent;
}
-// ---------------------------------------------------------------------------
\ No newline at end of file
+// ===========================================================================
\ No newline at end of file
diff --git a/scripts/server/account.js b/scripts/server/account.js
index c40b0922..0284a134 100644
--- a/scripts/server/account.js
+++ b/scripts/server/account.js
@@ -2,7 +2,7 @@
// Asshat-Gaming Roleplay
// https://github.com/VortrexFTW/gtac_asshat_rp
// Copyright (c) 2021 Asshat-Gaming (https://asshatgaming.com)
-// ---------------------------------------------------------------------------
+// ===========================================================================
// FILE: account.js
// DESC: Provides account functions and usage
// TYPE: Server (JavaScript)
@@ -13,7 +13,7 @@ function initAccountScript() {
logToConsole(LOG_DEBUG, "[Asshat.Account]: Account script initialized!");
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function loginCommand(command, params, client) {
if(!isPlayerRegistered(client)) {
@@ -30,7 +30,7 @@ function loginCommand(command, params, client) {
return true;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function autoLoginByIPCommand(command, params, client) {
let flagValue = getAccountSettingsFlagValue("autoLoginIP");
@@ -45,7 +45,7 @@ function autoLoginByIPCommand(command, params, client) {
return true;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function autoSelectLastCharacterCommand(command, params, client) {
let flagValue = getAccountSettingsFlagValue("autoSelectLastCharacter");
@@ -60,7 +60,7 @@ function autoSelectLastCharacterCommand(command, params, client) {
return true;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function toggleAccountGUICommand(command, params, client) {
let flagValue = getAccountSettingsFlagValue("noGUI");
@@ -97,7 +97,7 @@ function toggleAccountGUICommand(command, params, client) {
return true;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function toggleAccountServerLogoCommand(command, params, client) {
let flagValue = getAccountSettingsFlagValue("noServerLogo");
@@ -119,38 +119,40 @@ function toggleAccountServerLogoCommand(command, params, client) {
return true;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
// UNFINISHED!
// TO-DO: Make GUI, add command to generate code to add to auth app and command to input code returned by auth app
function toggleAccountTwoFactorAuthCommand(command, params, client) {
let flagValue = getAccountSettingsFlagValue("twoStepAuth");
- if(getPlayerData(client).emailAddress != "") {
+ if(getPlayerData(client).accountData.emailAddress != "") {
messagePlayerError(client, "You need to add your email to your account to use two-factor authentication.");
messagePlayerTip(client, "[#FFFFFF]Use [#AAAAAA]/setemail [#FFFFFF]to add your email.");
return false;
}
- if(!isValidEmailAddress(getPlayerData(client).emailAddress)) {
- messagePlayerError(client, "The email you previously added is not valid.");
- messagePlayerTip(client, "[#FFFFFF]Use [#AAAAAA]/setemail [#FFFFFF]to add a valid email.");
+ if(isAccountEmailVerified(getPlayerData(client).accountData)) {
+ messagePlayerError(client, "You need to verify your email to your account to use two-factor authentication.");
+ messagePlayerTip(client, "[#FFFFFF]Use [#AAAAAA]/verifyemail [#FFFFFF]to verify your email.");
return false;
}
if(!doesPlayerHaveTwoFactorAuthEnabled(client)) {
- getPlayerData(client).accountData.settings = getPlayerData(client).accountData.settings & ~flagValue;
- messagePlayerSuccess(client, `[#FFFFFF]Use this code to add your account into your authenticator app: [#AAAAAA]${addtoAuthenticatorCode}`);
+ getPlayerData(client).accountData.settings = addBitFlag(getPlayerData(client).accountData.settings, flagValue);
+ messagePlayerSuccess(client, `[#FFFFFF]You have turned ${getBoolRedGreenInlineColour(false)}ON [#FFFFFF] two factor authentication![#AAAAAA]${addtoAuthenticatorCode}`);
+ messagePlayerAlert(client, "You will be required to enter a code sent to your email every time you log on.");
logToConsole(LOG_DEBUG, `[Asshat.Account] ${getPlayerDisplayForConsole(client)} has toggled two-factor authentication ON for their account`);
} else {
- getPlayerData(client).accountData.settings = getPlayerData(client).accountData.settings | flagValue;
+ getPlayerData(client).accountData.settings = removeBitFlag(getPlayerData(client).accountData.settings, flagValue);
messagePlayerSuccess(client, `You have turned ${getBoolRedGreenInlineColour(false)}OFF [#FFFFFF]two-factor authentication for login.`);
+ messagePlayerAlert(client, "You won't be required to enter a code sent to your email every time you log on anymore.");
logToConsole(LOG_DEBUG, `[Asshat.Account] ${getPlayerDisplayForConsole(client)} has toggled two-factor authentication OFF for their account`);
}
return true;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function registerCommand(command, params, client) {
if(isPlayerRegistered(client)) {
@@ -169,7 +171,7 @@ function registerCommand(command, params, client) {
//messagePlayerAlert(client, "To play on the server, you will need to make a character.");
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function changePasswordCommand(command, params, client) {
if(areParamsEmpty(params)) {
@@ -196,12 +198,34 @@ function changePasswordCommand(command, params, client) {
messagePlayerSuccess(client, "Your password has been changed!");
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
+
+function setAccountChatScrollLinesCommand(command, params, client) {
+ if(areParamsEmpty(params)) {
+ messagePlayerSyntax(client, getCommandSyntaxText(command));
+ return false;
+ }
+
+ if(isNaN(params)) {
+ messagePlayerError(client, "The line amount must be a number!");
+ return false;
+ }
+
+ if(toInteger(params) < 1 || toInteger(params) > 6) {
+ messagePlayerError(client, "The line amount must be between 1 and 6!");
+ return false;
+ }
+
+ let lines = Math.ceil(toInteger(params));
+
+ getPlayerData(client).accountData.chatScrollLines = lines;
+ sendPlayerChatScrollLines(client, lines);
+ messagePlayerSuccess(client, `Your chatbox will now scroll ${toInteger(lines)} lines at a time!`);
+}
+
+// ===========================================================================
function setAccountEmailCommand(command, params, client) {
- messagePlayerError(client, `This command is not yet finished and will be available soon!`);
- return false;
-
if(areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
@@ -215,12 +239,61 @@ function setAccountEmailCommand(command, params, client) {
return false;
}
- // TO-DO: Command (like /verifyemail or use this one for second step too) to input verification code sent to email.
- //getPlayerData(client).accountData.emailAddress = emailAddress;
- messagePlayerSuccess(client, "Your password has been changed!");
+ //if(.emailAddress != "") {
+ // messagePlayerError(client, `Your email is already set!`);
+ // return false;
+ //}
+
+ if(getPlayerData(client).accountData.emailAddress != "" && isAccountEmailVerified(getPlayerData(client).accountData)) {
+ messagePlayerError(client, `You already set your email and verified it!`);
+ return false;
+ }
+
+ setAccountEmail(getPlayerData(client).accountData, emailAddress);
+
+ let emailVerificationCode = generateEmailVerificationCode();
+ setAccountEmailVerificationCode(getPlayerData(client).accountData, emailVerificationCode);
+ sendEmailVerificationEmail(client, emailVerificationCode);
+
+ messagePlayerSuccess(client, `Your email has been set!`);
+ messagePlayerAlert(client, `Please verify your email to enable extra account security and recovery features.`);
+ messagePlayerAlert(client, `A verification code and instructions have been sent to your email.`);
+ saveAccountToDatabase(getPlayerData(client).accountData);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
+
+function verifyAccountEmailCommand(command, params, client) {
+ if(areParamsEmpty(params)) {
+ messagePlayerSyntax(client, getCommandSyntaxText(command));
+ return false;
+ }
+
+ let splitParams = params.split(" ");
+ let verificationCode = splitParams[0];
+
+ if(isAccountEmailVerified(getPlayerData(client).accountData)) {
+ messagePlayerError(client, `You already verified your email!`);
+ return false;
+ }
+
+ if(module.hashing.sha512(verificationCode) != getPlayerData(client).accountData.emailVerificationCode) {
+ messagePlayerError(client, `Invalid email verification code! A new one has been created and sent to your email.`);
+ let emailVerificationCode = generateEmailVerificationCode();
+ setAccountEmailVerificationCode(getPlayerData(client).accountData, emailVerificationCode);
+ sendEmailVerificationEmail(client, emailVerificationCode);
+ return false;
+ }
+
+ getPlayerData(client).accountData.flags.moderation = addBitFlag(getPlayerData(client).accountData.flags.moderation, getModerationFlagValue("emailVerified"));
+ getPlayerData(client).accountData.emailVerificationCode = "";
+
+ messagePlayerSuccess(client, `Your email has been verified!`);
+ messagePlayerAlert(client, `You can now use your email for password resets, two-factor authentication, alerts, and more!`);
+ saveAccountToDatabase(getPlayerData(client).accountData);
+}
+
+// ===========================================================================
function setAccountDiscordCommand(command, params, client) {
messagePlayerError(client, `This command is not yet finished and will be available soon!`);
@@ -239,12 +312,12 @@ function setAccountDiscordCommand(command, params, client) {
return false;
}
- // TO-DO: Command (like /verifyemail or use this one for second step too) to input verification code sent to email.
+ // TO-DO: Command (like /verifydiscord or use this one for second step too) to input verification code sent to email.
//getPlayerData(client).accountData.emailAddress = emailAddress;
//messagePlayerSuccess(client, "Your discord account has been attached to your game account!");
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function isPlayerLoggedIn(client) {
if(isConsole(client)) {
@@ -258,7 +331,7 @@ function isPlayerLoggedIn(client) {
return false;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function isPlayerRegistered(client) {
if(isConsole(client)) {
@@ -274,14 +347,14 @@ function isPlayerRegistered(client) {
return false;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function doesPasswordMeetRequirements(password) {
// Will be added soon
return true;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function isAccountPasswordCorrect(accountData, password) {
if(accountData.password == password) {
@@ -291,13 +364,13 @@ function isAccountPasswordCorrect(accountData, password) {
return false;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function loadAccountFromName(accountName, fullLoad = false) {
let dbConnection = connectToDatabase();
if(dbConnection) {
accountName = escapeDatabaseString(dbConnection, accountName);
- let dbQueryString = `SELECT *, INET_NTOA(acct_ip) AS ipstring FROM acct_main WHERE acct_name = '${accountName}' LIMIT 1;`;
+ let dbQueryString = `SELECT acct_main.*, acct_svr.*, INET_NTOA(acct_ip) AS ipstring FROM acct_main INNER JOIN acct_svr ON acct_svr.acct_svr_acct = acct_main.acct_id AND acct_svr.acct_svr_svr = ${getServerId()} WHERE acct_name = '${accountName}' LIMIT 1;`;
let dbQuery = queryDatabase(dbConnection, dbQueryString);
if(dbQuery) {
if(dbQuery.numRows > 0) {
@@ -319,7 +392,7 @@ function loadAccountFromName(accountName, fullLoad = false) {
return false;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function loadAccountFromId(accountId, fullLoad = false) {
let dbConnection = connectToDatabase();
@@ -345,7 +418,7 @@ function loadAccountFromId(accountId, fullLoad = false) {
return false;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function getAccountHashingFunction() {
switch(toLowerCase(getGlobalConfig().accountPasswordHash)) {
@@ -384,7 +457,7 @@ function getAccountHashingFunction() {
}
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function isNameRegistered(name) {
let accountData = loadAccountFromName(name, true);
@@ -395,7 +468,7 @@ function isNameRegistered(name) {
return false;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function hashAccountPassword(name, password) {
let hashFunction = getAccountHashingFunction();
@@ -403,18 +476,20 @@ function hashAccountPassword(name, password) {
return hashFunction(saltedInfo);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function saltAccountInfo(name, password) {
return "ag.gaming." + toString(accountSaltHash) + "." + toString(name) + "." + toString(password);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function loginSuccess(client) {
logToConsole(LOG_DEBUG, `[Asshat.Account] ${getPlayerDisplayForConsole(client)} successfully logged in.`);
getPlayerData(client).loggedIn = true;
+ updateConnectionLogOnAuth(client, getPlayerData(client).accountData.databaseId);
+
if(doesPlayerHaveStaffPermission(client, "developer") || doesPlayerHaveStaffPermission(client, "manageServer")) {
logToConsole(LOG_WARN, `[Asshat.Account] ${getPlayerDisplayForConsole(client)} has needed permissions and is being given administrator access`);
client.administrator = true;
@@ -423,7 +498,7 @@ function loginSuccess(client) {
if(getPlayerData(client).subAccounts.length == 0) {
if(getServerConfig().useGUI && doesPlayerHaveGUIEnabled(client)) {
showPlayerPromptGUI(client, "You have no characters. Would you like to make one?", "No characters");
- setEntityData(client, "ag.prompt", AG_PROMPT_CREATEFIRSTCHAR, false);
+ getPlayerData(client).promptType = AG_PROMPT_CREATEFIRSTCHAR;
logToConsole(LOG_DEBUG, `[Asshat.Account] ${getPlayerDisplayForConsole(client)} is being shown the no characters prompt GUI`);
} else {
messagePlayerAlert(client, `You have no characters. Use /newchar to make one.`);
@@ -436,34 +511,74 @@ function loginSuccess(client) {
getPlayerData(client).accountData.ipAddress = client.ip;
sendRemovedWorldObjectsToPlayer(client);
- sendAccountKeyBindsToClient(client);
+ sendPlayerChatScrollLines(client, getPlayerData(client).accountData.chatScrollLines);
messagePlayerNormal(null, `👋 ${client.name} has joined the server`, getColourByName("softYellow"));
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function saveAccountToDatabase(accountData) {
let dbConnection = connectToDatabase();
if(dbConnection) {
+ //logToConsole(LOG_VERBOSE, `Escaping account data for ${getPlayerDisplayForConsole(client)}`);
let safePassword = escapeDatabaseString(dbConnection, accountData.password);
+ //logToConsole(LOG_VERBOSE, `${getPlayerDisplayForConsole(accountData.name)}'s password escaped successfully`);
let safeStaffTitle = escapeDatabaseString(dbConnection, accountData.staffTitle);
+ //logToConsole(LOG_VERBOSE, `${getPlayerDisplayForConsole(client)}'s staff title escaped successfully`);
let safeEmailAddress = escapeDatabaseString(dbConnection, accountData.emailAddress);
- //let safeIRCAccount = dbConnection.escapetoString(accountData.ircAccount);
+ //logToConsole(LOG_VERBOSE, `${getPlayerDisplayForConsole(client)}'s email address escaped successfully`);
+
+ let dbQueryString =
+ `UPDATE acct_main SET
+ acct_email='${safeEmailAddress}',
+ acct_pass='${safePassword}',
+ acct_discord=${accountData.discordAccount},
+ acct_ip=INET_ATON('${accountData.ipAddress}'),
+ acct_code_verifyemail='${accountData.emailVerificationCode}'
+ WHERE acct_id=${accountData.databaseId}`;
+
+ /*
+ acct_settings=${accountData.settings},
+ acct_staff_title='${safeStaffTitle}',
+ acct_staff_flags=${accountData.flags.admin},
+ acct_mod_flags=${accountData.flags.moderation},
+ */
+
+ //dbQueryString = dbQueryString.trim();
+ dbQueryString = dbQueryString.replace(/(?:\r\n|\r|\n|\t)/g, "");
- let dbQueryString = `UPDATE acct_main SET acct_pass='${safePassword}', acct_settings=${accountData.settings}, acct_staff_flags=${accountData.flags.admin}, acct_staff_title='${safeStaffTitle}', acct_mod_flags=${toString(accountData.flags.moderation)}, acct_discord=${toString(accountData.discordAccount)}, acct_email='${safeEmailAddress}', acct_ip=INET_ATON('${accountData.ipAddress}') WHERE acct_id=${accountData.databaseId}`;
let dbQuery = queryDatabase(dbConnection, dbQueryString);
- //freeDatabaseQuery(dbQuery);
+ freeDatabaseQuery(dbQuery);
+ dbQuery = null;
+
+ dbQueryString =
+ `UPDATE acct_svr SET
+ acct_svr_acct='${accountData.databaseId}',
+ acct_svr_settings=${accountData.flags.settings},
+ acct_svr_staff_title='${safeStaffTitle}',
+ acct_svr_staff_flags=${accountData.flags.admin},
+ acct_svr_mod_flags=${accountData.flags.moderation},
+ acct_svr_chat_scroll_lines=${accountData.chatScrollLines}
+ WHERE acct_svr_acct=${accountData.databaseId} AND acct_svr_svr = ${getServerId()}`;
+
+ //dbQueryString = dbQueryString.trim();
+ dbQueryString = dbQueryString.replace(/(?:\r\n|\r|\n|\t)/g, "");
+
+ dbQuery = queryDatabase(dbConnection, dbQueryString);
+ freeDatabaseQuery(dbQuery);
disconnectFromDatabase(dbConnection);
}
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function saveAccountKeyBindsDatabase(keyBindData) {
let dbConnection = connectToDatabase();
if(dbConnection) {
+ //logToConsole(LOG_VERBOSE, `Escaping account keybinds data for ${getPlayerDisplayForConsole(client)}`);
let safeCommandString = escapeDatabaseString(dbConnection, keyBindData.commandString);
+ //logToConsole(LOG_VERBOSE, `${getPlayerDisplayForConsole(client)}'s keybind command string escaped successfully`);
if(keyBindData.databaseId == 0) {
let dbQueryString = `INSERT INTO acct_hotkey (acct_hotkey_cmdstr, acct_hotkey_key, acct_hotkey_down, acct_hotkey_enabled) VALUES ('${safeCommandString}', ${keyBindData.key}, ${boolToInt(keyBindData.keyState)}, ${boolToInt(keyBindData.enabled)}, ${keyBindData.account}`;
keyBindData.databaseId = getDatabaseInsertId(dbConnection);
@@ -479,12 +594,13 @@ function saveAccountKeyBindsDatabase(keyBindData) {
}
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function saveAccountStaffNotesDatabase(staffNoteData) {
let dbConnection = connectToDatabase();
if(dbConnection) {
let safeNoteContent = escapeDatabaseString(dbConnection, staffNoteData.note);
+ //logToConsole(LOG_VERBOSE, `${getPlayerDisplayForConsole(client)}'s staff note string escaped successfully`);
if(staffNoteData.databaseId == 0) {
let dbQueryString = `INSERT INTO acct_note (acct_note_message, acct_note_who_added, acct_note_when_added, acct_note_server, acct_note_acct) VALUES ('${safeNoteContent}', ${staffNoteData.whoAdded}, UNIX_TIMESTAMP(), ${getServerId()}, ${staffNoteData.account}`;
staffNoteData.databaseId = getDatabaseInsertId(dbConnection);
@@ -496,7 +612,7 @@ function saveAccountStaffNotesDatabase(staffNoteData) {
}
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
/*
function saveAccountContactsDatabase(accountContactData) {
@@ -519,7 +635,7 @@ function saveAccountContactsDatabase(accountContactData) {
}
*/
-// ---------------------------------------------------------------------------
+// ===========================================================================
function createAccount(name, password, email = "") {
let dbConnection = connectToDatabase();
@@ -529,10 +645,11 @@ function createAccount(name, password, email = "") {
let safeName = escapeDatabaseString(dbConnection, name);
let safeEmail = escapeDatabaseString(dbConnection, email);
- let dbQuery = queryDatabase(dbConnection, `INSERT INTO acct_main (acct_name, acct_pass, acct_email) VALUES ('${safeName}', '${hashedPassword}', '${safeEmail}')`);
+ let dbQuery = queryDatabase(dbConnection, `INSERT INTO acct_main (acct_name, acct_pass, acct_email, acct_when_registered) VALUES ('${safeName}', '${hashedPassword}', '${safeEmail}', UNIX_TIMESTAMP())`);
if(getDatabaseInsertId(dbConnection) > 0) {
let accountData = loadAccountFromId(getDatabaseInsertId(dbConnection), true);
createDefaultKeybindsForAccount(accountData.databaseId);
+ createDefaultAccountServerData(accountData.databaseId);
return accountData;
}
}
@@ -540,10 +657,13 @@ function createAccount(name, password, email = "") {
return false;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function checkLogin(client, password) {
getPlayerData(client).loginAttemptsRemaining = getPlayerData(client).loginAttemptsRemaining-1;
+ if(getPlayerData(client).loginAttemptsRemaining <= 0) {
+ client.disconnect();
+ }
if(isPlayerLoggedIn(client)) {
logToConsole(LOG_WARN, `[Asshat.Account] ${getPlayerDisplayForConsole(client)} attempted to login but is already logged in`);
@@ -599,7 +719,7 @@ function checkLogin(client, password) {
loginSuccess(client);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function checkRegistration(client, password, confirmPassword = "", emailAddress = "") {
logToConsole(LOG_DEBUG, "[Asshat.Account]: Checking registration for " + toString(client.name));
@@ -685,24 +805,29 @@ function checkRegistration(client, password, confirmPassword = "", emailAddress
getPlayerData(client).loggedIn = true;
messagePlayerSuccess(client, "Your account has been created!");
+ messagePlayerAlert(client, "Don't forget to verify your email! A verification code has been sent to you");
messagePlayerAlert(client, "To play on the server, you will need to make a character.");
if(getServerConfig().useGUI && doesPlayerHaveGUIEnabled(client)) {
showPlayerRegistrationSuccessGUI(client);
showPlayerPromptGUI(client, "You have no characters. Would you like to make one?", "No Characters");
- setEntityData(client, "ag.prompt", AG_PROMPT_CREATEFIRSTCHAR, false);
+ getPlayerData(client).promptType = AG_PROMPT_CREATEFIRSTCHAR;
+
+ let emailVerificationCode = generateEmailVerificationCode();
+ setAccountEmailVerificationCode(getPlayerData(client).accountData, emailVerificationCode);
+ sendEmailVerificationEmail(client, emailVerificationCode);
} else {
messagePlayerAlert(client, `You have no characters. Use /newchar to make one.`);
}
};
-// ---------------------------------------------------------------------------
+// ===========================================================================
function isValidEmailAddress(emailAddress) {
return true;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function saveAllClientsToDatabase() {
logToConsole(LOG_DEBUG, "[Asshat.Account]: Saving all clients to database ...");
@@ -712,7 +837,7 @@ function saveAllClientsToDatabase() {
logToConsole(LOG_DEBUG, "[Asshat.Account]: All clients saved to database successfully!");
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function savePlayerToDatabase(client) {
if(getPlayerData(client) == null) {
@@ -727,22 +852,29 @@ function savePlayerToDatabase(client) {
saveAccountToDatabase(getPlayerData(client).accountData);
if(getPlayerData(client).currentSubAccount != -1) {
- let subAccountData = getPlayerCurrentSubAccount(client);
+ //let subAccountData = getPlayerCurrentSubAccount(client);
if(client.player != null) {
- subAccountData.spawnPosition = getPlayerPosition(client);
- subAccountData.spawnHeading = getPlayerHeading(client);
- subAccountData.interior = getPlayerInterior(client);
- subAccountData.dimension = getPlayerDimension(client);
+ if(getPlayerData(client).returnToPosition != null) {
+ getPlayerCurrentSubAccount(client).spawnPosition = getPlayerData(client).returnToPosition;
+ getPlayerCurrentSubAccount(client).spawnHeading = getPlayerData(client).returnToHeading;
+ getPlayerCurrentSubAccount(client).interior = getPlayerData(client).returnToInterior;
+ getPlayerCurrentSubAccount(client).dimension = getPlayerData(client).returnToDimension;
+ } else {
+ getPlayerCurrentSubAccount(client).spawnPosition = getPlayerPosition(client);
+ getPlayerCurrentSubAccount(client).spawnHeading = getPlayerHeading(client);
+ getPlayerCurrentSubAccount(client).interior = getPlayerInterior(client);
+ getPlayerCurrentSubAccount(client).dimension = getPlayerDimension(client);
+ }
}
- saveSubAccountToDatabase(subAccountData);
+ saveSubAccountToDatabase(getPlayerCurrentSubAccount(client));
}
logToConsole(LOG_DEBUG, `[Asshat.Account]: Saved client ${getPlayerDisplayForConsole(client)} to database successfully!`);
return true;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function initClient(client) {
if(isConsole(client)) {
@@ -753,6 +885,7 @@ function initClient(client) {
sendPlayerGUIInit(client);
showConnectCameraToPlayer(client);
+ //playRadioStreamForPlayer(client, getServerConfig().introMusicURL, true);
messageClient(`Please wait ...`, client, getColourByName("softGreen"));
setTimeout(function() {
@@ -794,23 +927,45 @@ function initClient(client) {
}, 2500);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function saveConnectionToDatabase(client) {
- let dbQueryString = `INSERT INTO conn_main (conn_when_connect, conn_server, conn_script_version, conn_game_version, conn_client_version) VALUES (UNIX_TIMESTAMP(), ${getServerConfig().databaseId}, '${scriptVersion}', '${client.gameVersion}', '0.0.0')`;
- return quickDatabaseQuery(dbQueryString);
+ let dbConnection = connectToDatabase();
+ if(dbConnection) {
+ let safeName = escapeDatabaseString(dbConnection, client.name);
+ let dbQueryString = `INSERT INTO conn_main (conn_when_connect, conn_server, conn_script_version, conn_game_version, conn_client_version, conn_name, conn_ip) VALUES (UNIX_TIMESTAMP(), ${getServerConfig().databaseId}, '${scriptVersion}', '${client.gameVersion}', '0.0.0', '${safeName}', INET_ATON('${client.ip}'))`;
+ let query = queryDatabase(dbConnection, dbQueryString);
+ setEntityData(client, "ag.connection", getDatabaseInsertId(dbConnection));
+ }
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function createDefaultKeybindsForAccount(accountDatabaseId) {
- for(let i in getGlobalConfig().defaultKeybinds) {
- let dbQueryString = `INSERT INTO acct_hotkey (acct_hotkey_acct, acct_hotkey_key, acct_hotkey_cmdstr, acct_hotkey_when_added, acct_hotkey_down) VALUES (${accountDatabaseId}, ${getGlobalConfig().defaultKeybinds[i].key}, '${getGlobalConfig().defaultKeybinds[i].commandString}', UNIX_TIMESTAMP(), ${boolToInt(getGlobalConfig().defaultKeybinds[i].keyState)})`;
+ logToConsole(LOG_DEBUG, `[Asshat.Account]: Creating default keybinds for account ${accountDatabaseId} ...`);
+ for(let j = 1 ; j <= 4 ; j++) {
+ logToConsole(LOG_DEBUG, `[Asshat.Account]: Creating default keybinds for account ${accountDatabaseId} on server ${j} ...`);
+ for(let i in getGlobalConfig().keyBind.defaultKeyBinds) {
+ logToConsole(LOG_DEBUG, `[Asshat.Account]: Creating default keybind ${i} for account ${accountDatabaseId} on server ${j} with key ${sdl.getKeyFromName(getGlobalConfig().keyBind.defaultKeyBinds[i].keyName.toLowerCase())} ...`);
+ let dbQueryString = `INSERT INTO acct_hotkey (acct_hotkey_acct, acct_hotkey_server, acct_hotkey_key, acct_hotkey_cmdstr, acct_hotkey_when_added, acct_hotkey_down) VALUES (${accountDatabaseId}, ${j}, ${sdl.getKeyFromName(getGlobalConfig().keyBind.defaultKeyBinds[i].keyName.toLowerCase())}, '${getGlobalConfig().keyBind.defaultKeyBinds[i].commandString}', UNIX_TIMESTAMP(), ${getGlobalConfig().keyBind.defaultKeyBinds[i].keyState})`;
+ quickDatabaseQuery(dbQueryString);
+ logToConsole(LOG_DEBUG, `[Asshat.Account]: Created default keybind ${i} for account ${accountDatabaseId} on server ${j} with key ${sdl.getKeyFromName(getGlobalConfig().keyBind.defaultKeyBinds[i].keyName.toLowerCase())}!`);
+ }
+ logToConsole(LOG_DEBUG, `[Asshat.Account]: Create default keybinds for account ${accountDatabaseId} on server ${j}!`);
+ }
+ logToConsole(LOG_DEBUG, `[Asshat.Account]: Created default keybinds for account ${accountDatabaseId} successfully!`);
+}
+
+// ===========================================================================
+
+function createDefaultAccountServerData(accountDatabaseId) {
+ for(let i = 1 ; i <= 4 ; i++) {
+ let dbQueryString = `INSERT INTO acct_svr (acct_svr_acct, acct_svr_svr) VALUES (${accountDatabaseId}, ${i})`;
quickDatabaseQuery(dbQueryString);
}
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function loadAccountKeybindsFromDatabase(accountDatabaseID) {
logToConsole(LOG_DEBUG, `[Asshat.Account]: Loading account keybinds for account ${accountDatabaseID} from database ...`);
@@ -821,7 +976,7 @@ function loadAccountKeybindsFromDatabase(accountDatabaseID) {
let dbAssoc;
if(dbConnection) {
- dbQuery = queryDatabase(dbConnection, `SELECT * FROM acct_hotkey WHERE acct_hotkey_enabled = 1 AND acct_hotkey_acct = ${accountDatabaseID}`);
+ dbQuery = queryDatabase(dbConnection, `SELECT * FROM acct_hotkey WHERE acct_hotkey_enabled = 1 AND acct_hotkey_acct = ${accountDatabaseID} AND acct_hotkey_server = ${getServerId()}`);
if(dbQuery) {
if(dbQuery.numRows > 0) {
while(dbAssoc = fetchQueryAssoc(dbQuery)) {
@@ -839,7 +994,7 @@ function loadAccountKeybindsFromDatabase(accountDatabaseID) {
return tempAccountKeybinds;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function loadAccountStaffNotesFromDatabase(accountDatabaseID) {
logToConsole(LOG_DEBUG, `[Asshat.Account]: Loading account staff notes for account ${accountDatabaseID} from database ...`);
@@ -868,7 +1023,7 @@ function loadAccountStaffNotesFromDatabase(accountDatabaseID) {
return tempAccountStaffNotes;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function loadAccountContactsFromDatabase(accountDatabaseID) {
logToConsole(LOG_DEBUG, `[Asshat.Account]: Loading account contacts for account ${accountDatabaseID} from database ...`);
@@ -897,7 +1052,7 @@ function loadAccountContactsFromDatabase(accountDatabaseID) {
return tempAccountContacts;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function loadAccountMessagesFromDatabase(accountDatabaseID) {
logToConsole(LOG_DEBUG, `[Asshat.Account]: Loading account messages for account ${accountDatabaseID} from database ...`);
@@ -926,7 +1081,7 @@ function loadAccountMessagesFromDatabase(accountDatabaseID) {
return tempAccountMessages;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function isAccountAutoIPLoginEnabled(accountData) {
let accountSettings = accountData.settings;
@@ -934,7 +1089,7 @@ function isAccountAutoIPLoginEnabled(accountData) {
return hasBitFlag(accountSettings, flagValue);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function doesPlayerHaveGUIEnabled(client) {
if(hasBitFlag(getPlayerData(client).accountData.settings, getAccountSettingsFlagValue("noGUI"))) {
@@ -944,7 +1099,7 @@ function doesPlayerHaveGUIEnabled(client) {
return true;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function doesPlayerHaveLogoEnabled(client) {
if(hasBitFlag(getPlayerData(client).accountData.settings, getAccountSettingsFlagValue("noServerLogo"))) {
@@ -954,7 +1109,7 @@ function doesPlayerHaveLogoEnabled(client) {
return true;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function doesPlayerHaveAutoLoginByIPEnabled(client) {
if(hasBitFlag(getPlayerData(client).accountData.settings, getAccountSettingsFlagValue("autoLoginIP"))) {
@@ -964,20 +1119,73 @@ function doesPlayerHaveAutoLoginByIPEnabled(client) {
return false;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function doesPlayerHaveAutoSelectLastCharacterEnabled(client) {
if(hasBitFlag(getPlayerData(client).accountData.settings, getAccountSettingsFlagValue("autoSelectLastCharacter"))) {
return true;
}
- return true;
+ return false;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function getPlayerStaffTitle(client) {
return getPlayerData(client).accountData.staffTitle;
}
-// ---------------------------------------------------------------------------
\ No newline at end of file
+// ===========================================================================
+
+function isAccountEmailVerified(accountData) {
+ return hasBitFlag(accountData.flags.moderation, getModerationFlagValue("emailVerified"));
+}
+
+// ===========================================================================
+
+function isAccountTwoFactorAuthenticationVerified(accountData) {
+ return hasBitFlag(accountData.flags.moderation, getModerationFlagValue("twoFactorAuthVerified"));
+}
+
+// ===========================================================================
+
+function setAccountEmail(accountData, emailAddress) {
+ accountData.emailAddress = emailAddress;
+}
+
+// ===========================================================================
+
+function setAccountEmailVerificationCode(accountData, emailVerificationCode) {
+ accountData.emailVerificationCode = module.hashing.sha512(emailVerificationCode);
+}
+
+// ===========================================================================
+
+function generateEmailVerificationCode() {
+ return generateRandomString(10);
+}
+
+// ===========================================================================
+
+function sendEmailVerificationEmail(client, emailVerificationCode) {
+ let emailBodyText = getEmailConfig().bodyContent.confirmEmail;
+ emailBodyText = emailBodyText.replace("{VERIFICATIONCODE}", emailVerificationCode);
+
+ sendEmail(getPlayerData(client).accountData.emailAddress, getPlayerData(client).accountData.name, `Confirm email on Asshat Gaming RP`, emailBodyText);
+}
+
+// ===========================================================================
+
+function verifyAccountEmail(accountData, verificationCode) {
+ let emailVerificationCode = generateRandomString(10);
+
+ let emailBodyText = getEmailConfig().bodyContent.confirmEmail;
+ emailBodyText = emailBodyText.replace("{VERIFICATIONCODE}", emailVerificationCode);
+
+ sendEmail(getPlayerData(client).accountData.emailAddress, getPlayerData(client).accountData.name, `Confirm email on Asshat Gaming RP`, emailBodyText);
+
+ getPlayerData(client).accountData.emailAddress = emailAddress;
+ getPlayerData(client).accountData.emailVerificationCode = module.hashing.sha512(emailVerificationCode);
+}
+
+// ===========================================================================
\ No newline at end of file
diff --git a/scripts/server/ammunation.js b/scripts/server/ammunation.js
deleted file mode 100644
index ea9357fc..00000000
--- a/scripts/server/ammunation.js
+++ /dev/null
@@ -1,9 +0,0 @@
-// ===========================================================================
-// Asshat-Gaming Roleplay
-// https://github.com/VortrexFTW/gtac_asshat_rp
-// Copyright (c) 2021 Asshat-Gaming (https://asshatgaming.com)
-// ---------------------------------------------------------------------------
-// FILE: ammunation.js
-// DESC: Provides ammunation functions and usage
-// TYPE: Server (JavaScript)
-// ===========================================================================
\ No newline at end of file
diff --git a/scripts/server/anticheat.js b/scripts/server/anticheat.js
index d075b9da..28997297 100644
--- a/scripts/server/anticheat.js
+++ b/scripts/server/anticheat.js
@@ -2,7 +2,7 @@
// Asshat-Gaming Roleplay
// https://github.com/VortrexFTW/gtac_asshat_rp
// Copyright (c) 2021 Asshat-Gaming (https://asshatgaming.com)
-// ---------------------------------------------------------------------------
+// ===========================================================================
// FILE: anticheat.js
// DESC: Provides anticheat functions and usage
// TYPE: Server (JavaScript)
@@ -14,7 +14,7 @@ function initAntiCheatScript() {
getServerData().antiCheat.blackListedGameScripts = loadAntiCheatGameScriptBlackListFromDatabase();
logToConsole(LOG_DEBUG, "[Asshat.AntiCheat]: Anticheat script initialized!");
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function loadAntiCheatGameScriptWhiteListFromDatabase() {
logToConsole(LOG_DEBUG, `[Asshat.AntiCheat] Loading whitelisted game scripts ...`);
@@ -38,7 +38,7 @@ function loadAntiCheatGameScriptWhiteListFromDatabase() {
return tempWhiteListedGameScripts;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function loadAntiCheatGameScriptBlackListFromDatabase() {
logToConsole(LOG_DEBUG, `[Asshat.AntiCheat] Loading blacklisted game scripts ...`);
@@ -62,4 +62,17 @@ function loadAntiCheatGameScriptBlackListFromDatabase() {
return tempBlackListedGameScripts;
}
-// ---------------------------------------------------------------------------
\ No newline at end of file
+// ===========================================================================
+
+function clearPlayerStateToEnterExitProperty(client) {
+ if(getPlayerData(client).pedState != AG_PEDSTATE_READY) {
+ if(getPlayerData(client).pedState == AG_PEDSTATE_ENTERINGVEHICLE) {
+ sendPlayerClearPedState(client);
+ getPlayerData(client).pedState = AG_PEDSTATE_READY;
+ } else {
+ return false;
+ }
+ }
+}
+
+// ===========================================================================
\ No newline at end of file
diff --git a/scripts/server/ban.js b/scripts/server/ban.js
index 4e66a0ee..d5fb7444 100644
--- a/scripts/server/ban.js
+++ b/scripts/server/ban.js
@@ -2,28 +2,20 @@
// Asshat-Gaming Roleplay
// https://github.com/VortrexFTW/gtac_asshat_rp
// Copyright (c) 2021 Asshat-Gaming (https://asshatgaming.com)
-// ---------------------------------------------------------------------------
+// ===========================================================================
// FILE: bans.js
// DESC: Provides ban functions and usage
// TYPE: Server (JavaScript)
// ===========================================================================
-const banType = {
- none: 0,
- account: 1,
- subAccount: 3,
- ipAddress: 4,
- uid: 5,
-};
-
-// ---------------------------------------------------------------------------
+// ===========================================================================
function initBanScript() {
- logToConsole(LOG_DEBUG, "[Asshat.Ban]: Initializing ban script ...");
- logToConsole(LOG_DEBUG, "[Asshat.Ban]: Ban script initialized!");
+ logToConsole(LOG_INFO, "[Asshat.Ban]: Initializing ban script ...");
+ logToConsole(LOG_INFO, "[Asshat.Ban]: Ban script initialized!");
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function accountBanCommand(command, params, client) {
if(areParamsEmpty(params)) {
@@ -37,12 +29,18 @@ function accountBanCommand(command, params, client) {
return false;
}
- messageAdminAction(`${getPlayerData(targetClient).accountData.name} has been banned from the server (account ban).`);
- banAccount(getPlayerData(targetClient).accountData.databaseId, getPlayerData(client).accountData.databaseId, "");
+ let splitParams = params.split(" ");
+ let targetClient = getPlayerFromParams(splitParams[0]);
+ let reason = splitParams.slice(1).join(" ");
+
+ logToConsole(LOG_WARN, `[Asshat.Ban]: ${getPlayerDisplayForConsole(targetClient)} (${getPlayerData(targetClient).accountData.name}) account was banned by ${getPlayerDisplayForConsole(client)}. Reason: ${reason}`);
+
+ messageAdminAction(`${getPlayerDisplayForConsole(targetClient)} (${getPlayerData(targetClient).accountData.name}) has been account banned.`);
+ banAccount(getPlayerData(targetClient).accountData.databaseId, getPlayerData(client).accountData.databaseId, reason);
disconnectPlayer(client);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function subAccountBanCommand(command, params, client, fromDiscord) {
if(areParamsEmpty(params)) {
@@ -60,12 +58,14 @@ function subAccountBanCommand(command, params, client, fromDiscord) {
let targetClient = getPlayerFromParams(splitParams[0]);
let reason = splitParams.slice(1).join(" ");
- messageAdminAction(`${getPlayerData(targetClient).currentSubAccountData.name} has been banned from the server (character ban).`);
+ logToConsole(LOG_WARN, `[Asshat.Ban]: ${getPlayerDisplayForConsole(targetClient)} (${getPlayerData(targetClient).accountData.name})'s subaccount was banned by ${getPlayerDisplayForConsole(client)}. Reason: ${reason}`);
+
+ messageAdminAction(`${getPlayerData(targetClient).currentSubAccountData.name} has been character banned.`);
banSubAccount(getPlayerData(targetClient).currentSubAccountData.databaseId, getPlayerData(client).accountData.databaseId, reason);
disconnectPlayer(client);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function ipBanCommand(command, params, client, fromDiscord) {
if(areParamsEmpty(params)) {
@@ -83,13 +83,13 @@ function ipBanCommand(command, params, client, fromDiscord) {
let targetClient = getPlayerFromParams(splitParams[0]);
let reason = splitParams.slice(1).join(" ");
- messageAdminAction(`${targetClient.name} has been banned from the server (IP ban).`);
+ messageAdminAction(`${targetClient.name} has been IP banned.`);
banIPAddress(targetClient.ip, getPlayerData(client).accountData.databaseId, reason);
server.banIP(targetClient.ip);
targetClient.disconnect();
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function subNetBanCommand(command, params, client, fromDiscord) {
if(areParamsEmpty(params)) {
@@ -112,7 +112,7 @@ function subNetBanCommand(command, params, client, fromDiscord) {
banSubNet(targetClient.ip, getSubNet(targetClient.ip, octetAmount), getPlayerData(client).accountData.databaseId, reason);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function banAccount(accountId, adminAccountId, reason) {
let dbConnection = connectToDatabase();
@@ -127,7 +127,7 @@ function banAccount(accountId, adminAccountId, reason) {
return false;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function banSubAccount(subAccountId, adminAccountId, reason) {
let dbConnection = connectToDatabase();
@@ -142,7 +142,7 @@ function banSubAccount(subAccountId, adminAccountId, reason) {
return false;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function banIPAddress(ipAddress, adminAccountId, reason) {
let dbConnection = connectToDatabase();
@@ -157,7 +157,7 @@ function banIPAddress(ipAddress, adminAccountId, reason) {
return false;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function banSubNet(ipAddressStart, ipAddressEnd, adminAccountId, reason) {
let dbConnection = connectToDatabase();
@@ -172,7 +172,7 @@ function banSubNet(ipAddressStart, ipAddressEnd, adminAccountId, reason) {
return false;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function unbanAccount(accountId, adminAccountId) {
let dbConnection = connectToDatabase();
@@ -186,7 +186,7 @@ function unbanAccount(accountId, adminAccountId) {
return false;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function unbanSubAccount(subAccountId, adminAccountId) {
let dbConnection = connectToDatabase();
@@ -200,7 +200,7 @@ function unbanSubAccount(subAccountId, adminAccountId) {
return false;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function unbanIPAddress(ipAddress, adminAccountId) {
let dbConnection = connectToDatabase();
@@ -214,7 +214,7 @@ function unbanIPAddress(ipAddress, adminAccountId) {
return false;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function unbanSubNet(ipAddressStart, ipAddressEnd, adminAccountId) {
let dbConnection = connectToDatabase();
@@ -228,7 +228,7 @@ function unbanSubNet(ipAddressStart, ipAddressEnd, adminAccountId) {
return false;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function isAccountBanned(accountId) {
let bans = getServerData().bans;
@@ -243,7 +243,7 @@ function isAccountBanned(accountId) {
return false;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function isSubAccountBanned(subAccountId) {
let bans = getServerData().bans;
@@ -258,7 +258,7 @@ function isSubAccountBanned(subAccountId) {
return false;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function isIpAddressBanned(ipAddress) {
let bans = getServerData().bans;
@@ -273,5 +273,5 @@ function isIpAddressBanned(ipAddress) {
return false;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
diff --git a/scripts/server/bitflag.js b/scripts/server/bitflag.js
index b297eb64..a9a4a23f 100644
--- a/scripts/server/bitflag.js
+++ b/scripts/server/bitflag.js
@@ -2,13 +2,13 @@
// Asshat-Gaming Roleplay
// https://github.com/VortrexFTW/gtac_asshat_rp
// Copyright (c) 2021 Asshat-Gaming (https://asshatgaming.com)
-// ---------------------------------------------------------------------------
+// ===========================================================================
// FILE: bitflags.js
// DESC: Provides bitwise operations, functions and usage
// TYPE: Server (JavaScript)
// ===========================================================================
-// ---------------------------------------------------------------------------
+// ===========================================================================
let serverBitFlags = {
staffFlags: {},
@@ -17,9 +17,10 @@ let serverBitFlags = {
clanFlags: {},
accountSettingsFlags: {},
subAccountSettingsFlags: {},
+ accountFlags: {},
};
-// ---------------------------------------------------------------------------
+// ===========================================================================
let serverBitFlagKeys = {
staffFlagKeys: [
@@ -34,6 +35,7 @@ let serverBitFlagKeys = {
"manageJobs",
"manageItems",
"manageWorld",
+ "manageAntiCheat",
"developer",
],
moderationFlagKeys: [
@@ -44,13 +46,24 @@ let serverBitFlagKeys = {
"gunBanned",
"jobBanned",
"ammuBanned",
+ "noSkinCustomization",
+ "desyncWeapons",
+ "hackerWorld",
+ "adminJailed",
+ "exemptFromAntiCheat",
+ "exemptFromBans",
+ "forceTutorial",
+ "characterNameNeedsStaffApproval",
+ "emailVerified",
+ "twoFactorAuthVerified",
],
factionFlagKeys: [
"none",
"police",
"medical",
"fire",
- "government"
+ "government",
+ "generic",
],
clanFlagKeys: [
"none",
@@ -83,6 +96,7 @@ let serverBitFlagKeys = {
"manageVehicles",
"manageHouses",
"manageBusinesses",
+ "manageNPCs",
"owner",
],
accountSettingsFlagKeys: [
@@ -95,13 +109,109 @@ let serverBitFlagKeys = {
"autoLoginIP",
"noServerLogo",
"autoSelectLastCharacter",
+ "showRealTimeClock",
+ "useGUIForItems",
+ "useRadialWheelItems", // If this is disabled, use MMORPG-style hotbar IF useGUIForItems is enabled
+ "disableKeyBinds",
+ "showTimedRandomTips",
+ "showActionTips",
+ ],
+ npcTriggerTypeKeys: [
+ "farProximity", // Comes within a far distance of NPC
+ "mediumProximity", // Comes within a medium distance of NPC
+ "nearProximity", // Comes within a close distance of NPC
+ "enterLineOfSight", // Enters the NPC's line of sight
+ "exitLineOfSight", // Leaves the NPC's line of sight
+ "pedCollision", // Bumps into ped on foot
+ "vehicleCollision", // Bumps into ped with a vehicle
+ "shootGun", // Shoots a gun (target isn't a factor, it's just about only shooting a gun in general)
+ "swingMelee", // Swings a melee weapon (target doesnt matter, it's just about only swinging a melee weapon in general)
+ "hotwireVehicleStart", // Begin attempt to hotwire a vehicle
+ "hotwireVehicleFail", // Failed to hotwire a vehicle
+ "hotwireVehicleSucceed", // Succeeded at hotwiring a vehicle
+ "vehicleAlarmStart", // Vehicle alarm goes off
+ "vehicleAlarmStop", // Vehicle alarm shuts off (disabled, battery dead, damaged, or just turned off legitly)
+ "sirenStart", // Any vehicle with a siren that gets activated
+ "sirenStop", // Any vehicle with a siren that gets deactivated
+ "vehicleEnter", // Enters any vehicle
+ "vehicleExit", // Exits any vehicle
+ "propertyEnter", // Enters any interior
+ "propertyExit", // Exits any interior
+ "attackedByMelee", // Any element is attacked by melee weapon
+ "attackedByGun", // Any element is attacked by gun
+ "attackedByFist", // Any element is attacked by fist
+ ],
+ npcTriggerConditionTypeKeys: [
+ "isInLineOfSight",
+ "isFarProximity",
+ "isMediumProximity",
+ "isNearProximity",
+ "isEnemyClan",
+ "isAllyClan",
+ "isSameClan",
+ "isNotInClan",
+ "isLawEnforcement",
+ "isFirefighter",
+ "isParamedic",
+ "isCriminal",
+ "hasWantedLevel",
+ "isSelfVehicle",
+ "isPlayerVehicle",
+ "isOtherVehicle",
+ "isClanVehicle",
+ "isEmergencyVehicle",
+ "isPoliceVehicle",
+ "isDriver",
+ "isInFrontSeat",
+ "isInSeatId",
+ "vehicleLocked",
+ "vehicleHotwired",
+ "isPistol",
+ "isShotgun",
+ "isAutomatic",
+ "isRifle",
+ "isAssaultRifle",
+ "isSniper",
+ "isRPG",
+ "isFlameThrower",
+ "isTalking",
+ "isShouting",
+ "isWhispering",
+ ],
+ npcTriggerResponseTypeKeys: [
+ "shout",
+ "talk",
+ "whisper",
+ "switchWeapon",
+ "shootWeapon",
+ "aimWeapon",
+ "fleeSprint",
+ "fleeWalk",
+ "fleeRun",
+ "attackMelee",
+ "attackFist",
+ "walkToward",
+ "runToward",
+ "sprintToward",
+ "crouch",
+ "phoneCall",
+ "walkieTalkieMessage",
+ "switchRadioStation",
+ "toggleSiren",
+ "fleeTo",
+ "driveTo",
+ "enterVehicle",
+ "exitVehicle",
+ "pullOutOfVehicle",
+ "enterProperty",
+ "searchArea",
],
- subAccountSettingsFlagKeys: [],
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function initBitFlagScript() {
+ logToConsole(LOG_INFO, "[Asshat.BitFlag]: Initializing bit flag script ...");
serverBitFlags.staffFlags = createBitFlagTable(serverBitFlagKeys.staffFlagKeys);
serverBitFlags.moderationFlags = createBitFlagTable(serverBitFlagKeys.moderationFlagKeys);
serverBitFlags.accountSettingsFlags = createBitFlagTable(serverBitFlagKeys.accountSettingsFlagKeys);
@@ -109,16 +219,14 @@ function initBitFlagScript() {
serverBitFlags.clanFlags = createBitFlagTable(serverBitFlagKeys.clanFlagKeys);
serverBitFlags.clanPermissionFlags = createBitFlagTable(serverBitFlagKeys.clanPermissionFlagKeys);
serverBitFlags.factionFlags = createBitFlagTable(serverBitFlagKeys.factionFlagKeys);
+ serverBitFlags.npcTriggerTypes = createBitFlagTable(serverBitFlagKeys.npcTriggerTypeKeys);
+ serverBitFlags.npcTriggerConditionTypes = createBitFlagTable(serverBitFlagKeys.npcTriggerConditionTypeKeys);
+ serverBitFlags.npcTriggerResponseTypes = createBitFlagTable(serverBitFlagKeys.npcTriggerResponseTypeKeys);
+ logToConsole(LOG_INFO, "[Asshat.BitFlag]: Bit flag script initialized successfully!");
return true;
}
-// ---------------------------------------------------------------------------
-
-function addBitFlagCommandHandlers() {
- return true;
-}
-
-// ---------------------------------------------------------------------------
+// ===========================================================================
function createBitFlagTable(keyNames) {
let bitVal = 0;
@@ -134,7 +242,7 @@ function createBitFlagTable(keyNames) {
return bitTable;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function hasBitFlag(allFlags, checkForFlag) {
if(allFlags == 0) {
@@ -148,7 +256,7 @@ function hasBitFlag(allFlags, checkForFlag) {
return (allFlags & checkForFlag);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function doesPlayerHaveStaffPermission(client, requiredFlags) {
if(isConsole(client)) {
@@ -176,7 +284,7 @@ function doesPlayerHaveStaffPermission(client, requiredFlags) {
return false;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function doesPlayerHaveClanPermission(client, requiredFlags) {
if(isConsole(client)) {
@@ -206,7 +314,7 @@ function doesPlayerHaveClanPermission(client, requiredFlags) {
return false;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function getStaffFlagValue(flagName) {
if(flagName == "all") {
@@ -220,7 +328,7 @@ function getStaffFlagValue(flagName) {
return serverBitFlags.staffFlags[flagName];
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function getClanFlagValue(flagName) {
if(flagName == "all") {
@@ -234,7 +342,7 @@ function getClanFlagValue(flagName) {
return getServerBitFlags().clanFlags[flagName];
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function getAccountSettingsFlagValue(flagName) {
if(flagName == "all") {
@@ -248,21 +356,21 @@ function getAccountSettingsFlagValue(flagName) {
return serverBitFlags.accountSettingsFlags[flagName];
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
-function getAccountFlagsFlagValue(flagName) {
+function getModerationFlagValue(flagName) {
if(flagName == "all") {
return -1;
}
- if(typeof serverBitFlags.accountFlags[flagName] === "undefined") {
+ if(typeof serverBitFlags.moderationFlags[flagName] === "undefined") {
return false;
}
- return serverBitFlags.accountFlags[flagName];
+ return serverBitFlags.moderationFlags[flagName];
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function givePlayerStaffFlag(client, flagName) {
if(!getStaffFlagValue(flagName)) {
@@ -273,7 +381,7 @@ function givePlayerStaffFlag(client, flagName) {
return true;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function takePlayerStaffFlag(client, flagName) {
if(!getStaffFlagValue(flagName)) {
@@ -284,19 +392,19 @@ function takePlayerStaffFlag(client, flagName) {
return true;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function addBitFlag(allFlags, flagValue) {
return allFlags | flagValue;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function removeBitFlag(allFlags, flagValue) {
return allFlags & ~flagValue;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function takePlayerStaffFlag(client, flagName) {
if(!getStaffFlagValue(flagName)) {
@@ -307,23 +415,39 @@ function takePlayerStaffFlag(client, flagName) {
return true;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function clearPlayerStaffFlags(client) {
getPlayerData(client).accountData.flags.admin = getStaffFlagValue("none");
return true;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function getServerBitFlags() {
return serverBitFlags;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function getServerBitFlagKeys() {
return serverBitFlagKeys;
}
-// ---------------------------------------------------------------------------
\ No newline at end of file
+// ===========================================================================
+
+function createBitwiseTable(tableKeys) {
+ let bitVal = 0;
+ let bitTable = {};
+ let incVal = 1;
+
+ for(let i in tableKeys) {
+ let key = tableKeys[i];
+ bitTable[key] = bitVal;
+ bitVal = 1 << incVal;
+ incVal++;
+ }
+ return bitTable;
+}
+
+// ===========================================================================
\ No newline at end of file
diff --git a/scripts/server/business.js b/scripts/server/business.js
index 1a55f7cd..c330c207 100644
--- a/scripts/server/business.js
+++ b/scripts/server/business.js
@@ -2,23 +2,33 @@
// Asshat-Gaming Roleplay
// https://github.com/VortrexFTW/gtac_asshat_rp
// Copyright (c) 2021 Asshat-Gaming (https://asshatgaming.com)
-// ---------------------------------------------------------------------------
+// ===========================================================================
// FILE: business.js
// DESC: Provides business functions and usage
// TYPE: Server (JavaScript)
// ===========================================================================
function initBusinessScript() {
- logToConsole(LOG_DEBUG, "[Asshat.Business]: Initializing business script ...");
+ logToConsole(LOG_INFO, "[Asshat.Business]: Initializing business script ...");
getServerData().businesses = loadBusinessesFromDatabase();
- createAllBusinessPickups();
- createAllBusinessBlips();
+
+ cacheAllBusinessItems();
+
+ if(getServerConfig().createBusinessPickups) {
+ createAllBusinessPickups();
+ }
+
+ if(getServerConfig().createBusinessPickups) {
+ createAllBusinessBlips();
+ }
+
setAllBusinessIndexes();
- logToConsole(LOG_DEBUG, "[Asshat.Business]: Business script initialized successfully!");
+
+ logToConsole(LOG_INFO, "[Asshat.Business]: Business script initialized successfully!");
return true;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function loadBusinessFromId(businessId) {
let dbConnection = connectToDatabase();
@@ -36,10 +46,10 @@ function loadBusinessFromId(businessId) {
return false;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function loadBusinessesFromDatabase() {
- logToConsole(LOG_DEBUG, "[Asshat.Business]: Loading businesses from database ...");
+ logToConsole(LOG_INFO, "[Asshat.Business]: Loading businesses from database ...");
let tempBusinesses = [];
let dbConnection = connectToDatabase();
@@ -54,7 +64,7 @@ function loadBusinessesFromDatabase() {
let tempBusinessData = new serverClasses.businessData(dbAssoc);
tempBusinessData.locations = loadBusinessLocationsFromDatabase(tempBusinessData.databaseId);
tempBusinesses.push(tempBusinessData);
- logToConsole(LOG_DEBUG, `[Asshat.Business]: Business '${tempBusinessData.name}' (ID ${tempBusinessData.databaseId}) loaded from database successfully!`);
+ logToConsole(LOG_INFO, `[Asshat.Business]: Business '${tempBusinessData.name}' (ID ${tempBusinessData.databaseId}) loaded from database successfully!`);
}
}
freeDatabaseQuery(dbQuery);
@@ -62,28 +72,30 @@ function loadBusinessesFromDatabase() {
disconnectFromDatabase(dbConnection);
}
- logToConsole(LOG_DEBUG, `[Asshat.Business]: ${tempBusinesses.length} businesses loaded from database successfully!`);
+ logToConsole(LOG_INFO, `[Asshat.Business]: ${tempBusinesses.length} businesses loaded from database successfully!`);
return tempBusinesses;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function loadBusinessLocationsFromDatabase(businessId) {
- //logToConsole(LOG_DEBUG, "[Asshat.Business]: Loading locations from database ...");
+ logToConsole(LOG_VERBOSE, `[Asshat.Business]: Loading business locations for business ${businessId} from database ...`);
let tempBusinessLocations = [];
let dbConnection = connectToDatabase();
let dbQuery = null;
let dbAssoc;
+ let dbQueryString = "";
if(dbConnection) {
- dbQuery = queryDatabase(dbConnection, "SELECT * FROM `biz_loc` WHERE `biz_loc_biz` = " + toString(businessId));
+ dbQueryString = `SELECT * FROM biz_loc WHERE biz_loc_biz = ${businessId}`;
+ dbQuery = queryDatabase(dbConnection, dbQueryString);
if(dbQuery) {
if(dbQuery.numRows > 0) {
while(dbAssoc = fetchQueryAssoc(dbQuery)) {
let tempBusinessLocationData = new serverClasses.businessLocationData(dbAssoc);
tempBusinessLocations.push(tempBusinessLocationData);
- //logToConsole(LOG_DEBUG, `[Asshat.Business]: Location '${tempBusinessLocationData.name}' loaded from database successfully!`);
+ logToConsole(LOG_VERBOSE, `[Asshat.Business]: Location '${tempBusinessLocationData.name}' loaded from database successfully!`);
}
}
freeDatabaseQuery(dbQuery);
@@ -91,11 +103,11 @@ function loadBusinessLocationsFromDatabase(businessId) {
disconnectFromDatabase(dbConnection);
}
- //logToConsole(LOG_DEBUG, `[Asshat.Business]: ${tempBusinessLocations.length} location for business ${businessId} loaded from database successfully!`);
+ logToConsole(LOG_VERBOSE, `[Asshat.Business]: ${tempBusinessLocations.length} location for business ${businessId} loaded from database successfully!`);
return tempBusinessLocations;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function createBusinessCommand(command, params, client) {
let tempBusinessData = createBusiness(params, getPlayerPosition(client), toVector3(0.0, 0.0, 0.0), getGameConfig().pickupModels[getServerGame()].business, getGameConfig().blipSprites[getServerGame()].business, getPlayerInterior(client), getPlayerDimension(client));
@@ -111,11 +123,11 @@ function createBusinessCommand(command, params, client) {
messageAdmins(`[#AAAAAA]${client.name} [#FFFFFF]created business [#0099FF]${tempBusinessData.name}`);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function createBusinessLocationCommand(command, params, client) {
if(!isPlayerSpawned(client)) {
- messagePlayerError("You must be spawned to use this command!");
+ messagePlayerError(client, "You must be spawned to use this command!");
return false;
}
@@ -127,7 +139,7 @@ function createBusinessLocationCommand(command, params, client) {
}
if(!getBusinessData(businessId)) {
- messagePlayerError("Business not found!");
+ messagePlayerError(client, "Business not found!");
return false;
}
@@ -137,7 +149,7 @@ function createBusinessLocationCommand(command, params, client) {
messageAdmins(`[#AAAAAA]${client.name} [#FFFFFF]created location [#0099FF]${params} [#FFFFFF]for business [#0099FF]${tempBusinessData.name}`);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function createBusiness(name, entrancePosition, exitPosition, entrancePickupModel = -1, entranceBlipModel = -1, entranceInteriorId = 0, entranceVirtualWorld = 0, exitInteriorId = -1, exitVirtualWorld = -1, exitPickupModel = -1, exitBlipModel = -1) {
let tempBusinessData = new serverClasses.businessData(false);
@@ -160,7 +172,7 @@ function createBusiness(name, entrancePosition, exitPosition, entrancePickupMode
return tempBusinessData;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function deleteBusinessCommand(command, params, client) {
let businessId = (isPlayerInAnyBusiness(client)) ? getPlayerBusiness(client) : getClosestBusinessEntrance(getPlayerPosition(client));
@@ -170,7 +182,7 @@ function deleteBusinessCommand(command, params, client) {
}
if(!getBusinessData(businessId)) {
- messagePlayerError("Business not found!");
+ messagePlayerError(client, "Business not found!");
return false;
}
@@ -178,7 +190,7 @@ function deleteBusinessCommand(command, params, client) {
deleteBusiness(businessId, getPlayerData(client).accountData.databaseId);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function deleteBusinessLocationCommand(command, params, client) {
//let businessId = toInteger(splitParams[1]);
@@ -186,7 +198,7 @@ function deleteBusinessLocationCommand(command, params, client) {
//messagePlayerSuccess(client, `Business '${tempBusinessData.name} deleted!`);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function setBusinessNameCommand(command, params, client) {
let newBusinessName = toString(params);
@@ -194,7 +206,7 @@ function setBusinessNameCommand(command, params, client) {
let businessId = (isPlayerInAnyBusiness(client)) ? getPlayerBusiness(client) : getClosestBusinessEntrance(getPlayerPosition(client));
if(!getBusinessData(businessId)) {
- messagePlayerError("Business not found!");
+ messagePlayerError(client, "Business not found!");
return false;
}
@@ -204,19 +216,19 @@ function setBusinessNameCommand(command, params, client) {
messageAdmins(`[#AAAAAA]${client.name} [#FFFFFF]renamed business [#0099FF]${oldBusinessName} [#FFFFFF]to [#0099FF]${newBusinessName}`);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function setBusinessOwnerCommand(command, params, client) {
let newBusinessOwner = getPlayerFromParams(params);
let businessId = (isPlayerInAnyBusiness(client)) ? getPlayerBusiness(client) : getClosestBusinessEntrance(getPlayerPosition(client));
if(!newBusinessOwner) {
- messagePlayerError("Player not found!");
+ messagePlayerError(client, "Player not found!");
return false;
}
if(!getBusinessData(businessId)) {
- messagePlayerError("Business not found!");
+ messagePlayerError(client, "Business not found!");
return false;
}
@@ -225,19 +237,19 @@ function setBusinessOwnerCommand(command, params, client) {
messageAdmins(`[#AAAAAA]${client.name} [#FFFFFF]set business [#0099FF]${getBusinessData(businessId).name} [#FFFFFF]owner to [#AAAAAA]${newBusinessOwner.name}`);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function setBusinessClanCommand(command, params, client) {
let clanId = getClanFromParams(params);
let businessId = (isPlayerInAnyBusiness(client)) ? getPlayerBusiness(client) : getClosestBusinessEntrance(getPlayerPosition(client));
if(!getBusinessData(businessId)) {
- messagePlayerError("Business not found!");
+ messagePlayerError(client, "Business not found!");
return false;
}
if(!getClanData(clanId)) {
- messagePlayerError("Clan not found!");
+ messagePlayerError(client, "Clan not found!");
return false;
}
@@ -246,7 +258,7 @@ function setBusinessClanCommand(command, params, client) {
messageAdmins(`[#AAAAAA]${client.name} [#FFFFFF]set business [#0099FF]${getBusinessData(businessId).name} [#FFFFFF]owner to the [#FF9900]${getClanData(clanId).name} [#FFFFFF]clan`);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function setBusinessJobCommand(command, params, client) {
let businessId = (isPlayerInAnyBusiness(client)) ? getPlayerBusiness(client) : getClosestBusinessEntrance(getPlayerPosition(client));
@@ -263,12 +275,12 @@ function setBusinessJobCommand(command, params, client) {
}
if(!getBusinessData(businessId)) {
- messagePlayerError("Business not found!");
+ messagePlayerError(client, "Business not found!");
return false;
}
if(!getJobData(jobId)) {
- messagePlayerError("Job not found!");
+ messagePlayerError(client, "Job not found!");
return false;
}
@@ -277,7 +289,7 @@ function setBusinessJobCommand(command, params, client) {
messageAdmins(`[#AAAAAA]${client.name} [#FFFFFF]set business [#0099FF]${getBusinessData(businessId).name} [#FFFFFF]owner to the [#FFFF00]${getJobData(jobId).name} [#FFFFFF]job`);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function setBusinessPublicCommand(command, params, client) {
let businessId = (isPlayerInAnyBusiness(client)) ? getPlayerBusiness(client) : getClosestBusinessEntrance(getPlayerPosition(client));
@@ -287,7 +299,7 @@ function setBusinessPublicCommand(command, params, client) {
}
if(!getBusinessData(businessId)) {
- messagePlayerError("Business not found!");
+ messagePlayerError(client, "Business not found!");
return false;
}
@@ -296,7 +308,7 @@ function setBusinessPublicCommand(command, params, client) {
messageAdmins(`[#AAAAAA]${client.name} [#FFFFFF]set business [#0099FF]${getBusinessData(businessId).name} [#FFFFFF]owner set to [#AAAAAA]public`);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function lockBusinessCommand(command, params, client) {
let businessId = (isPlayerInAnyBusiness(client)) ? getPlayerBusiness(client) : getClosestBusinessEntrance(getPlayerPosition(client));
@@ -306,7 +318,7 @@ function lockBusinessCommand(command, params, client) {
}
if(!getBusinessData(businessId)) {
- messagePlayerError("Business not found!");
+ messagePlayerError(client, "Business not found!");
return false;
}
@@ -315,15 +327,15 @@ function lockBusinessCommand(command, params, client) {
messagePlayerSuccess(client, `${getLockedUnlockedEmojiFromBool((getBusinessData(businessId).locked))} Business [#0099FF]${getBusinessData(businessId).name} [#FFFFFF]${getLockedUnlockedTextFromBool((getBusinessData(businessId).locked))}!`);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function setBusinessEntranceFeeCommand(command, params, client) {
let splitParams = params.split(" ");
let entranceFee = toInteger(splitParams[0]) || 0;
- let businessId = getBusinessFromParams(splitParams[1]) || (isPlayerInAnyBusiness(client)) ? getPlayerBusiness(client) : getClosestBusinessEntrance(getPlayerPosition(client));
+ let businessId = (isPlayerInAnyBusiness(client)) ? getPlayerBusiness(client) : getClosestBusinessEntrance(getPlayerPosition(client));
if(!getBusinessData(businessId)) {
- messagePlayerError("Business not found!");
+ messagePlayerError(client, "Business not found!");
return false;
}
@@ -331,7 +343,7 @@ function setBusinessEntranceFeeCommand(command, params, client) {
messageAdmins(`[#AAAAAA]${client.name} [#FFFFFF]set business [#0099FF]${getBusinessData(businessId).name} [#FFFFFF]entrance fee to [#AAAAAAA]$${entranceFee}`);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function getBusinessInfoCommand(command, params, client) {
let businessId = (isPlayerInAnyBusiness(client)) ? getPlayerBusiness(client) : getClosestBusinessEntrance(getPlayerPosition(client));
@@ -372,12 +384,12 @@ function getBusinessInfoCommand(command, params, client) {
messagePlayerInfo(client, `🏢 [#0099FF][Business Info] [#FFFFFF]Name: [#AAAAAA]${getBusinessData(businessId).name}, [#FFFFFF]Owner: [#AAAAAA]${ownerName} (${getBusinessOwnerTypeText(getBusinessData(businessId).ownerType)}), [#FFFFFF]Locked: [#AAAAAA]${getYesNoFromBool(intToBool(getBusinessData(businessId).locked))}, [#FFFFFF]ID: [#AAAAAA]${businessId}/${getBusinessData(businessId).databaseId}`);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function setBusinessPickupCommand(command, params, client) {
let splitParams = params.split(" ");
let typeParam = splitParams[0] || "business";
- let businessId = getBusinessFromParams(splitParams[1]) || (isPlayerInAnyBusiness(client)) ? getPlayerBusiness(client) : getClosestBusinessEntrance(getPlayerPosition(client));
+ let businessId = (isPlayerInAnyBusiness(client)) ? getPlayerBusiness(client) : getClosestBusinessEntrance(getPlayerPosition(client));
if(!getBusinessData(businessId)) {
messagePlayerError(client, "Business not found!");
@@ -404,12 +416,12 @@ function setBusinessPickupCommand(command, params, client) {
messageAdmins(`[#AAAAAA]${client.name} [#FFFFFF]set business [#0099FF]${getBusinessData(businessId).name} [#FFFFFF]pickup display to [#AAAAAA]${toLowerCase(typeParam)}'!`);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function setBusinessInteriorTypeCommand(command, params, client) {
let splitParams = params.split(" ");
let typeParam = splitParams[0] || "business";
- let businessId = getBusinessFromParams(splitParams[1]) || (isPlayerInAnyBusiness(client)) ? getPlayerBusiness(client) : getClosestBusinessEntrance(getPlayerPosition(client));
+ let businessId = (isPlayerInAnyBusiness(client)) ? getPlayerBusiness(client) : getClosestBusinessEntrance(getPlayerPosition(client));
if(!getBusinessData(businessId)) {
messagePlayerError(client, "Business not found!");
@@ -453,13 +465,13 @@ function setBusinessInteriorTypeCommand(command, params, client) {
createBusinessExitPickup(businessId);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function setBusinessBlipCommand(command, params, client) {
let splitParams = params.split(" ");
let typeParam = splitParams[0] || "business";
- let businessId = getBusinessFromParams(splitParams[1]) || (isPlayerInAnyBusiness(client)) ? getPlayerBusiness(client) : getClosestBusinessEntrance(getPlayerPosition(client));
+ let businessId = (isPlayerInAnyBusiness(client)) ? getPlayerBusiness(client) : getClosestBusinessEntrance(getPlayerPosition(client));
if(!getBusinessData(businessId)) {
messagePlayerError(client, "Business not found!");
@@ -486,7 +498,87 @@ function setBusinessBlipCommand(command, params, client) {
messageAdmins(`[#AAAAAA]${client.name} [#FFFFFF]set business [#0099FF]${getBusinessData(businessId).name} [#FFFFFF]blip display to [#AAAAAA]${toLowerCase(typeParam)}`);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
+
+function giveDefaultItemsToBusinessCommand(command, params, client) {
+ let splitParams = params.split(" ");
+
+ let typeParam = splitParams[0] || "business";
+ let businessId = (isPlayerInAnyBusiness(client)) ? getPlayerBusiness(client) : getClosestBusinessEntrance(getPlayerPosition(client));
+
+ if(!getBusinessData(businessId)) {
+ messagePlayerError(client, "Business not found!");
+ return false;
+ }
+
+ if(!isNaN(typeParam)) {
+ }
+
+ if(isNull(getGameConfig().defaultBusinessItems[getServerGame()][typeParam])) {
+ messagePlayerError(client, "Invalid business items type! Use a business items type name");
+ messagePlayerInfo(client, `Blip Types: [#AAAAAA]${Object.keys(getGameConfig().defaultBusinessItems[getServerGame()]).join(", ")}`)
+ return false;
+ }
+
+ for(let i in getGameConfig().defaultBusinessItems[getServerGame()][typeParam]) {
+ let itemTypeId = getItemTypeFromParams(getGameConfig().defaultBusinessItems[getServerGame()][typeParam][i][0]);
+ let itemTypeData = getItemTypeData(itemTypeId);
+ if(itemTypeData) {
+ let newItemIndex = createItem(itemTypeId, itemTypeData.orderValue, AG_ITEM_OWNER_BIZFLOOR, getBusinessData(businessId).databaseId, getGameConfig().defaultBusinessItems[getServerGame()][typeParam][i][1]);
+ getItemData(newItemIndex).buyPrice = applyServerInflationMultiplier(itemTypeData.orderPrice)*getGameConfig().defaultBusinessItems[getServerGame()][typeParam][i][2];
+ }
+ }
+
+ cacheBusinessItems(businessId);
+ updateBusinessPickupLabelData(businessId);
+ messageAdmins(`[#AAAAAA]${client.name} [#FFFFFF]gave business [#0099FF]${getBusinessData(businessId).name} [#FFFFFF]the default items for ${toLowerCase(typeParam)}`);
+}
+
+// ===========================================================================
+
+function deleteBusinessFloorItemsCommand(command, params, client) {
+ let splitParams = params.split(" ");
+
+ let typeParam = splitParams[0] || "business";
+ let businessId = (isPlayerInAnyBusiness(client)) ? getPlayerBusiness(client) : getClosestBusinessEntrance(getPlayerPosition(client));
+
+ if(!getBusinessData(businessId)) {
+ messagePlayerError(client, "Business not found!");
+ return false;
+ }
+
+ for(let i in getBusinessData(businessId).floorItemCache) {
+ deleteItem(getBusinessData(businessId).floorItemCache);
+ }
+
+ cacheBusinessItems(businessId);
+
+ messageAdmins(`[#AAAAAA]${client.name} [#FFFFFF]deleted all on-sale items for business [#0099FF]${getBusinessData(businessId).name}`);
+}
+
+// ===========================================================================
+
+function deleteBusinessStorageItemsCommand(command, params, client) {
+ let splitParams = params.split(" ");
+
+ let typeParam = splitParams[0] || "business";
+ let businessId = (isPlayerInAnyBusiness(client)) ? getPlayerBusiness(client) : getClosestBusinessEntrance(getPlayerPosition(client));
+
+ if(!getBusinessData(businessId)) {
+ messagePlayerError(client, "Business not found!");
+ return false;
+ }
+
+ for(let i in getBusinessData(businessId).storageItemCache) {
+ deleteItem(getBusinessData(businessId).storageItemCache);
+ }
+
+ cacheBusinessItems(businessId);
+
+ messageAdmins(`[#AAAAAA]${client.name} [#FFFFFF]deleted all stored items for business [#0099FF]${getBusinessData(businessId).name}`);
+}
+
+// ===========================================================================
function withdrawFromBusinessCommand(command, params, client) {
if(areParamsEmpty(params)) {
@@ -497,27 +589,53 @@ function withdrawFromBusinessCommand(command, params, client) {
let splitParams = params.split(" ");
let amount = toInteger(splitParams[0]) || 0;
- let businessId = getBusinessFromParams(splitParams[1]) || (isPlayerInAnyBusiness(client)) ? getPlayerBusiness(client) : getClosestBusinessEntrance(getPlayerPosition(client));
+ let businessId = (isPlayerInAnyBusiness(client)) ? getPlayerBusiness(client) : getClosestBusinessEntrance(getPlayerPosition(client));
if(!getBusinessData(businessId)) {
- messagePlayerError("Business not found!");
+ messagePlayerError(client, "Business not found!");
return false;
}
- let tempBusinessData = getServerData().businesses.filter(b => b.databaseId == businessId)[0];
-
- if(getServerData().businesses[businessId].till < amount) {
- messagePlayerError(client, `Business '${tempBusinessData.name}' doesn't have that much money! Use /bizbalance.`);
+ if(getBusinessData(businessId).till < amount) {
+ messagePlayerError(client, `Business [#0099FF]${tempBusinessData.name} doesn't have that much money! Use /bizbalance.`);
return false;
}
- getServerData().businesses[businessId].till -= amount;
+ getBusinessData(businessId).till -= amount;
getPlayerCurrentSubAccount(client).cash += amount;
updatePlayerCash(client);
- messagePlayerSuccess(client, `You withdrew $${amount} from business '${tempBusinessData.name}''s till'`);
+ messagePlayerSuccess(client, `You withdrew $${amount} from business [#0099FF]${getBusinessData(businessId).name} till`);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
+
+function setBusinessBuyPriceCommand(command, params, client) {
+ if(areParamsEmpty(params)) {
+ messagePlayerSyntax(client, getCommandSyntaxText(command));
+ return false;
+ }
+
+ let splitParams = params.split(" ");
+
+ let amount = toInteger(splitParams[0]) || 0;
+ let businessId = (isPlayerInAnyBusiness(client)) ? getPlayerBusiness(client) : getClosestBusinessEntrance(getPlayerPosition(client));
+
+ if(!getBusinessData(businessId)) {
+ messagePlayerError(client, "Business not found!");
+ return false;
+ }
+
+ if(amount < 0) {
+ messagePlayerError(client, `The amount can't be less than 0!`);
+ return false;
+ }
+
+ getBusinessData(businessId).buyPrice = amount;
+ setEntityData(getBusinessData(businessId).entrancePickup, "ag.label.price", getBusinessData(businessId).buyPrice, true);
+ messagePlayerSuccess(client, `[#FFFFFF]You set business [#0099FF]${getBusinessData(businessId).name}'s [#FFFFFF]for-sale price to [#AAAAAA]$${amount}`);
+}
+
+// ===========================================================================
function depositIntoBusinessCommand(command, params, client) {
if(areParamsEmpty(params)) {
@@ -528,7 +646,7 @@ function depositIntoBusinessCommand(command, params, client) {
let splitParams = params.split(" ");
let amount = toInteger(splitParams[0]) || 0;
- let businessId = getBusinessFromParams(splitParams[1]) || (isPlayerInAnyBusiness(client)) ? getPlayerBusiness(client) : getClosestBusinessEntrance(getPlayerPosition(client));
+ let businessId = (isPlayerInAnyBusiness(client)) ? getPlayerBusiness(client) : getClosestBusinessEntrance(getPlayerPosition(client));
if(!getBusinessData(businessId)) {
messagePlayerError(client, "Business not found!");
@@ -540,13 +658,13 @@ function depositIntoBusinessCommand(command, params, client) {
return false;
}
- getServerData().businesses[businessId].till += amount;
+ getBusinessData(businessId).till += amount;
getPlayerCurrentSubAccount(client).cash -= amount;
updatePlayerCash(client);
- messagePlayerSuccess(client, `You deposited $${amount} into business '${tempBusinessData.name}''s till'`);
+ messagePlayerSuccess(client, `You deposited $${amount} into business [#0099FF]${getBusinessData(businessId).name} [#FFFFFF]till`);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function orderItemForBusinessCommand(command, params, client) {
if(areParamsEmpty(params)) {
@@ -554,38 +672,59 @@ function orderItemForBusinessCommand(command, params, client) {
return false;
}
- let splitParams = params.split(" ");
-
- let itemType = getItemTypeFromParams(splitParams[0]);
- let amount = toInteger(splitParams[1]) || 1;
- let sellPrice = toInteger(splitParams[2]) || 0;
- let businessId = (isPlayerInAnyBusiness(client)) ? getPlayerBusiness(client) : getClosestBusinessEntrance(getPlayerPosition(client));
-
- if(!getBusinessData(businessId)) {
- messagePlayerError(client, "Business not found!");
+ if(!areThereEnoughParams(params, 3, " ")) {
+ messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
+ let splitParams = params.split(" ");
+ let itemType = getItemTypeFromParams(splitParams.slice(0,-2).join(" "));
+
if(!getItemTypeData(itemType)) {
messagePlayerError(client, "Invalid item type name or ID!");
messagePlayerInfo(client, "Use [#AAAAAA]/itemtypes [#FFFFFF]for a list of items");
return false;
}
+ let pricePerItem = getOrderPriceForItemType(itemType);
- let orderTotalCost = getItemTypeData(itemType).orderPrice*getServerConfig().inflationMultiplier*getItemTypeData(itemType).demandMultiplier*getItemTypeData(itemType).supplyMultiplier*getItemTypeData(itemType).riskMultiplier*amount;
+ let amount = toInteger(splitParams.slice(-2, -1)) || 1;
+ let value = toInteger(splitParams.slice(-1)) || getItemTypeData(itemType).capacity;
+ let businessId = (isPlayerInAnyBusiness(client)) ? getPlayerBusiness(client) : getClosestBusinessEntrance(getPlayerPosition(client));
+ logToConsole(LOG_DEBUG, `[Asshat.Business] ${getPlayerDisplayForConsole(client)} is ordering ${amount} ${splitParams.slice(0,-2).join(" ")} (${value})`);
+
+ if(!getBusinessData(businessId)) {
+ messagePlayerError(client, "You must be inside or near a business door!");
+ return false;
+ }
+
+ let orderTotalCost = pricePerItem*amount;
+
+ //getPlayerData(client).promptType = AG_PROMPT_BIZORDER;
+ getPlayerData(client).businessOrderAmount = amount;
+ getPlayerData(client).businessOrderBusiness = businessId;
+ getPlayerData(client).businessOrderItem = itemType;
+ getPlayerData(client).businessOrderValue = value;
+ getPlayerData(client).businessOrderCost = orderTotalCost;
+
+ showPlayerPrompt(client, AG_PROMPT_BIZORDER, `Ordering ${amount} ${getPluralForm(getItemTypeData(itemType).name)} (${getItemValueDisplay(itemType, value)}) at $${pricePerItem} each will cost a total of $${orderTotalCost}`, "Business Order Cost");
+}
+
+// ===========================================================================
+
+function orderItemForBusiness(businessId, itemType, amount) {
if(getBusinessData(businessId).till < orderTotalCost) {
let neededAmount = orderTotalCost-getBusinessData(businessId).till;
- messagePlayerError(client, `The business doesn't have enough money (needs [#AAAAAA]$${neededAmount} [#FFFFFF]more)! Use [#AAAAAA]/bizdeposit [#FFFFFF]to add money to the business.`);
+ //messagePlayerError(client, `The business doesn't have enough money (needs [#AAAAAA]$${neededAmount} [#FFFFFF]more)! Use [#AAAAAA]/bizdeposit [#FFFFFF]to add money to the business.`);
return false;
}
getBusinessData(businessId).till -= orderTotalCost;
addToBusinessInventory(businessId, itemType, amount);
- messagePlayerSuccess(client, `You ordered ${amount} ${getPluralForm(getItemTypeData(itemType).name)} at $${getItemTypeData(itemType).orderPrice} each for business [#0099FF]'${getBusinessData(businessId).name} [#FFFFFF] and set their sell price to [#AAAAAA]$${sellPrice}`);
+ //messagePlayerSuccess(client, `You ordered ${amount} ${getPluralForm(getItemTypeData(itemType).name)} (${getItemValueDisplay(itemType, value)}) at $${getItemTypeData(itemType).orderPrice} each for business [#0099FF]${getBusinessData(businessId).name}`);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function viewBusinessTillAmountCommand(command, params, client) {
let businessId = (isPlayerInAnyBusiness(client)) ? getPlayerBusiness(client) : getClosestBusinessEntrance(getPlayerPosition(client));
@@ -599,10 +738,39 @@ function viewBusinessTillAmountCommand(command, params, client) {
return false;
}
- messagePlayerSuccess(client, `Business '${getServerData().businesses[businessId].name}' till has $'${getServerData().businesses[businessId].till}'!`);
+ messagePlayerSuccess(client, `Business [#0099FF]${getBusinessData(businessId).name} [#FFFFFF]till has [#AAAAAA]$${getBusinessData(businessId).till}`);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
+
+function buyBusinessCommand(command, params, client) {
+ let businessId = (isPlayerInAnyBusiness(client)) ? getPlayerBusiness(client) : getClosestBusinessEntrance(getPlayerPosition(client));
+
+ if(!getBusinessData(businessId)) {
+ messagePlayerError(client, "Business not found!");
+ return false;
+ }
+
+ if(getBusinessData(businessId).buyPrice <= 0) {
+ messagePlayerError(client, `Business [#0099FF]${getBusinessData(businessId).name} [#FFFFFF]is not for sale!`);
+ return false;
+ }
+
+ if(getPlayerCurrentSubAccount(client).cash < getBusinessData(businessId).buyPrice) {
+ messagePlayerError(client, `You don't have enough money to buy business [#0099FF]${getBusinessData(businessId).name}!`);
+ return false;
+ }
+
+ getBusinessData(client).ownerType = AG_BIZOWNER_PLAYER;
+ getBusinessData(client).ownerId = getPlayerCurrentSubAccount(client).databaseId;
+ getBusinessData(client).buyPrice = 0;
+
+ updateBusinessPickupLabelData(businessId);
+
+ messagePlayerSuccess(client, `Business [#0099FF]${getBusinessData(businessId).name} [#FFFFFF]till has [#AAAAAA]$${getBusinessData(businessId).till}`);
+}
+
+// ===========================================================================
function moveBusinessEntranceCommand(command, params, client) {
let businessId = toInteger((isPlayerInAnyBusiness(client)) ? getPlayerBusiness(client) : getClosestBusinessEntrance(getPlayerPosition(client)));
@@ -629,7 +797,7 @@ function moveBusinessEntranceCommand(command, params, client) {
messageAdmins(`[#AAAAAA]${client.name} [#FFFFFF]moved business [#0099FF]${getBusinessData(businessId).name} [#FFFFFF]entrance to their position`);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function moveBusinessExitCommand(command, params, client) {
let businessId = toInteger((isPlayerInAnyBusiness(client)) ? getPlayerBusiness(client) : getClosestBusinessEntrance(getPlayerPosition(client)));
@@ -656,7 +824,7 @@ function moveBusinessExitCommand(command, params, client) {
messageAdmins(`[#AAAAAA]${client.name} [#FFFFFF]moved business [#0099FF]${getBusinessData(businessId).name} [#FFFFFF]exit to their position`);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function getBusinessDataFromDatabaseId(databaseId) {
let matchingBusinesses = getServerData().businesses.filter(b => b.databaseId == businessId)
@@ -666,7 +834,7 @@ function getBusinessDataFromDatabaseId(databaseId) {
return false;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function getClosestBusinessEntrance(position) {
let closest = 0;
@@ -678,7 +846,7 @@ function getClosestBusinessEntrance(position) {
return closest;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function isPlayerInAnyBusiness(client) {
if(doesEntityDataExist(client, "ag.inBusiness")) {
@@ -688,17 +856,17 @@ function isPlayerInAnyBusiness(client) {
return false;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function getPlayerBusiness(client) {
if(doesEntityDataExist(client, "ag.inBusiness")) {
return getEntityData(client, "ag.inBusiness");
}
- return false;
+ return -1;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function saveAllBusinessesToDatabase() {
for(let i in getServerData().businesses) {
@@ -706,7 +874,7 @@ function saveAllBusinessesToDatabase() {
}
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function saveBusinessToDatabase(businessId) {
let tempBusinessData = getServerData().businesses[businessId]
@@ -715,12 +883,94 @@ function saveBusinessToDatabase(businessId) {
if(dbConnection) {
let safeBusinessName = escapeDatabaseString(dbConnection, tempBusinessData.name);
if(tempBusinessData.databaseId == 0) {
- let dbQueryString = `INSERT INTO biz_main (biz_server, biz_name, biz_owner_type, biz_owner_id, biz_locked, biz_entrance_fee, biz_till, biz_entrance_pos_x, biz_entrance_pos_y, biz_entrance_pos_z, biz_entrance_rot_z, biz_entrance_int, biz_entrance_vw, biz_exit_pos_x, biz_exit_pos_y, biz_exit_pos_z, biz_exit_rot_z, biz_exit_int, biz_exit_vw, biz_has_interior) VALUES (${getServerId()}, '${safeBusinessName}', ${tempBusinessData.ownerType}, ${tempBusinessData.ownerId}, ${boolToInt(tempBusinessData.locked)}, ${tempBusinessData.entranceFee}, ${tempBusinessData.till}, ${tempBusinessData.entrancePosition.x}, ${tempBusinessData.entrancePosition.y}, ${tempBusinessData.entrancePosition.z}, ${tempBusinessData.entranceRotation}, ${tempBusinessData.entranceInterior}, ${tempBusinessData.entranceDimension}, ${tempBusinessData.exitPosition.x}, ${tempBusinessData.exitPosition.y}, ${tempBusinessData.exitPosition.z}, ${tempBusinessData.exitRotation}, ${tempBusinessData.exitInterior}, ${tempBusinessData.databaseId+getGlobalConfig().businessDimensionStart}, ${boolToInt(tempBusinessData.hasInterior)})`;
+ let dbQueryString = `INSERT INTO biz_main (
+ biz_server,
+ biz_name,
+ biz_owner_type,
+ biz_owner_id,
+ biz_locked,
+ biz_entrance_fee,
+ biz_till,
+ biz_entrance_pos_x,
+ biz_entrance_pos_y,
+ biz_entrance_pos_z,
+ biz_entrance_rot_z,
+ biz_entrance_int,
+ biz_entrance_vw,
+ biz_entrance_pickup,
+ biz_entrance_blip,
+ biz_exit_pos_x,
+ biz_exit_pos_y,
+ biz_exit_pos_z,
+ biz_exit_rot_z,
+ biz_exit_int,
+ biz_exit_vw,
+ biz_exit_pickup,
+ biz_exit_blip,
+ biz_has_interior
+ ) VALUES (
+ ${getServerId()},
+ '${safeBusinessName}',
+ ${tempBusinessData.ownerType},
+ ${tempBusinessData.ownerId},
+ ${boolToInt(tempBusinessData.locked)},
+ ${tempBusinessData.entranceFee},
+ ${tempBusinessData.till},
+ ${tempBusinessData.entrancePosition.x},
+ ${tempBusinessData.entrancePosition.y},
+ ${tempBusinessData.entrancePosition.z},
+ ${tempBusinessData.entranceRotation},
+ ${tempBusinessData.entranceInterior},
+ ${tempBusinessData.entranceDimension},
+ ${tempBusinessData.entrancePickupModel},
+ ${tempBusinessData.entranceBlipModel},
+ ${tempBusinessData.exitPosition.x},
+ ${tempBusinessData.exitPosition.y},
+ ${tempBusinessData.exitPosition.z},
+ ${tempBusinessData.exitRotation},
+ ${tempBusinessData.exitInterior},
+ ${tempBusinessData.databaseId+getGlobalConfig().businessDimensionStart},
+ ${tempBusinessData.exitPickupModel},
+ ${tempBusinessData.exitBlipModel},
+ ${boolToInt(tempBusinessData.hasInterior)}
+ )`;
queryDatabase(dbConnection, dbQueryString);
getServerData().businesses[businessId].databaseId = getDatabaseInsertId(dbConnection);
} else {
- let dbQueryString = `UPDATE biz_main SET biz_name='${safeBusinessName}', biz_owner_type=${tempBusinessData.ownerType}, biz_owner_id=${tempBusinessData.ownerId}, biz_locked=${boolToInt(tempBusinessData.locked)}, biz_entrance_fee=${tempBusinessData.entranceFee}, biz_till=${tempBusinessData.till}, biz_entrance_pos_x=${tempBusinessData.entrancePosition.x}, biz_entrance_pos_y=${tempBusinessData.entrancePosition.y}, biz_entrance_pos_z=${tempBusinessData.entrancePosition.z}, biz_entrance_rot_z=${tempBusinessData.entranceRotation}, biz_entrance_int=${tempBusinessData.entranceInterior}, biz_entrance_vw=${tempBusinessData.entranceDimension}, biz_exit_pos_x=${tempBusinessData.exitPosition.x}, biz_exit_pos_y=${tempBusinessData.exitPosition.y}, biz_exit_pos_z=${tempBusinessData.exitPosition.z}, biz_exit_rot_z=${tempBusinessData.exitRotation}, biz_exit_int=${tempBusinessData.exitInterior}, biz_exit_vw=${tempBusinessData.exitDimension}, biz_has_interior=${boolToInt(tempBusinessData.hasInterior)} WHERE biz_id=${tempBusinessData.databaseId}`;
- queryDatabase(dbConnection, dbQueryString);
+
+ let dbQueryString =
+ `UPDATE biz_main SET
+ biz_name='${safeBusinessName}',
+ biz_owner_type=${tempBusinessData.ownerType},
+ biz_owner_id=${tempBusinessData.ownerId},
+ biz_locked=${boolToInt(tempBusinessData.locked)},
+ biz_entrance_fee=${tempBusinessData.entranceFee},
+ biz_till=${tempBusinessData.till},
+ biz_entrance_pos_x=${tempBusinessData.entrancePosition.x},
+ biz_entrance_pos_y=${tempBusinessData.entrancePosition.y},
+ biz_entrance_pos_z=${tempBusinessData.entrancePosition.z},
+ biz_entrance_rot_z=${tempBusinessData.entranceRotation},
+ biz_entrance_int=${tempBusinessData.entranceInterior},
+ biz_entrance_vw=${tempBusinessData.entranceDimension},
+ biz_entrance_pickup=${tempBusinessData.entrancePickupModel},
+ biz_entrance_blip=${tempBusinessData.entranceBlipModel},
+ biz_exit_pos_x=${tempBusinessData.exitPosition.x},
+ biz_exit_pos_y=${tempBusinessData.exitPosition.y},
+ biz_exit_pos_z=${tempBusinessData.exitPosition.z},
+ biz_exit_rot_z=${tempBusinessData.exitRotation},
+ biz_exit_int=${tempBusinessData.exitInterior},
+ biz_exit_vw=${tempBusinessData.exitDimension},
+ biz_exit_pickup=${tempBusinessData.exitPickupModel},
+ biz_exit_blip=${tempBusinessData.exitBlipModel},
+ biz_has_interior=${boolToInt(tempBusinessData.hasInterior)},
+ biz_buy_price=${tempBusinessData.buyPrice}
+ WHERE biz_id=${tempBusinessData.databaseId}`;
+
+ dbQueryString = dbQueryString.replace(/(?:\r\n|\r|\n|\t)/g, "");
+
+ let dbQuery = queryDatabase(dbConnection, dbQueryString);
+ freeDatabaseQuery(dbQuery);
+ disconnectFromDatabase(dbConnection);
}
disconnectFromDatabase(dbConnection);
return true;
@@ -730,7 +980,7 @@ function saveBusinessToDatabase(businessId) {
return false;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function createAllBusinessPickups() {
for(let i in getServerData().businesses) {
@@ -739,7 +989,7 @@ function createAllBusinessPickups() {
}
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function createAllBusinessBlips() {
for(let i in getServerData().businesses) {
@@ -748,7 +998,7 @@ function createAllBusinessBlips() {
}
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function createBusinessEntrancePickup(businessId) {
if(getBusinessData(businessId).entrancePickupModel != -1) {
@@ -761,19 +1011,12 @@ function createBusinessEntrancePickup(businessId) {
getBusinessData(businessId).entrancePickup = gta.createPickup(pickupModelId, getBusinessData(businessId).entrancePosition);
getBusinessData(businessId).entrancePickup.onAllDimensions = false;
getBusinessData(businessId).entrancePickup.dimension = getBusinessData(businessId).entranceDimension;
- setEntityData(getBusinessData(businessId).entrancePickup, "ag.owner.type", AG_PICKUP_BUSINESS_ENTRANCE, false);
- setEntityData(getBusinessData(businessId).entrancePickup, "ag.owner.id", businessId, false);
- setEntityData(getBusinessData(businessId).entrancePickup, "ag.label.type", AG_LABEL_BUSINESS, true);
- setEntityData(getBusinessData(businessId).entrancePickup, "ag.label.name", getBusinessData(businessId).name, true);
- setEntityData(getBusinessData(businessId).entrancePickup, "ag.label.locked", getBusinessData(businessId).locked, true);
- if(getBusinessData(businessId).buyPrice > 0) {
- setEntityData(getBusinessData(businessId).entrancePickup, "ag.label.price", getBusinessData(businessId).buyPrice, true);
- }
+ updateBusinessPickupLabelData(businessId);
addToWorld(getBusinessData(businessId).entrancePickup);
}
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function createBusinessEntranceBlip(businessId) {
if(getBusinessData(businessId).entranceBlipModel != -1) {
@@ -783,7 +1026,7 @@ function createBusinessEntranceBlip(businessId) {
blipModelId = getBusinessData(businessId).entranceBlipModel;
}
- getBusinessData(businessId).entranceBlip = gta.createBlip(getBusinessData(businessId).entrancePosition, blipModelId, 1, getColourByName("businessBlue"));
+ getBusinessData(businessId).entranceBlip = gta.createBlip(blipModelId, getBusinessData(businessId).entrancePosition, 1, getColourByName("businessBlue"));
getBusinessData(businessId).entranceBlip.onAllDimensions = false;
getBusinessData(businessId).entranceBlip.dimension = getBusinessData(businessId).entranceDimension;
//getBusinessData(businessId).entranceBlip.interior = getBusinessData(businessId).entranceInterior;
@@ -793,7 +1036,7 @@ function createBusinessEntranceBlip(businessId) {
}
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function createBusinessExitPickup(businessId) {
if(getBusinessData(businessId).hasInterior) {
@@ -808,15 +1051,12 @@ function createBusinessExitPickup(businessId) {
getBusinessData(businessId).exitPickup.onAllDimensions = false;
getBusinessData(businessId).exitPickup.dimension = getBusinessData(businessId).exitDimension;
//getBusinessData(businessId).exitPickup.interior = getBusinessData(businessId).exitInterior;
- setEntityData(getBusinessData(businessId).exitPickup, "ag.owner.type", AG_PICKUP_BUSINESS_EXIT, false);
- setEntityData(getBusinessData(businessId).exitPickup, "ag.owner.id", businessId, false);
- setEntityData(getBusinessData(businessId).exitPickup, "ag.label.type", AG_LABEL_EXIT, true);
addToWorld(getBusinessData(businessId).exitPickup);
}
}
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function createBusinessExitBlip(businessId) {
if(getBusinessData(businessId).hasInterior) {
@@ -827,7 +1067,7 @@ function createBusinessExitBlip(businessId) {
blipModelId = getBusinessData(businessId).exitBlipModel;
}
- getBusinessData(businessId).exitBlip = gta.createBlip(getBusinessData(businessId).exitPosition, blipModelId, 1, getColourByName("businessBlue"));
+ getBusinessData(businessId).exitBlip = gta.createBlip(blipModelId, getBusinessData(businessId).exitPosition, 1, getColourByName("businessBlue"));
getBusinessData(businessId).exitBlip.onAllDimensions = false;
getBusinessData(businessId).exitBlip.dimension = getBusinessData(businessId).entranceDimension;
//getBusinessData(businessId).exitBlip.interior = getBusinessData(businessId).exitInterior;
@@ -838,7 +1078,7 @@ function createBusinessExitBlip(businessId) {
}
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function deleteBusiness(businessId, deletedBy = 0) {
let tempBusinessData = getServerData().businesses[businessId];
@@ -865,13 +1105,13 @@ function deleteBusiness(businessId, deletedBy = 0) {
getServerData().businesses.splice(businessId, 1);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function removePlayersFromBusiness(businessId) {
getClients().forEach(function(client) {
if(doesBusinessHaveInterior(businessId)) {
- if(doesEntityDataExist(client, "ag.inBusiness")) {
- if(getEntityData(client, "ag.inBusiness") == businessId) {
+ if(isPlayerInAnyBusiness(client)) {
+ if(getPlayerBusiness(client) == businessId) {
exitBusiness(client);
}
}
@@ -879,7 +1119,7 @@ function removePlayersFromBusiness(businessId) {
});
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function removePlayerFromBusinesses(client) {
if(isPlayerInAnyBusiness(client)) {
@@ -887,7 +1127,7 @@ function removePlayerFromBusinesses(client) {
}
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function exitBusiness(client) {
let businessId = getEntityData(client, "ag.inBusiness");
@@ -899,7 +1139,7 @@ function exitBusiness(client) {
removeEntityData(client, "ag.inBusiness");
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function getBusinessOwnerTypeText(ownerType) {
switch(ownerType) {
@@ -921,7 +1161,7 @@ function getBusinessOwnerTypeText(ownerType) {
}
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function getBusinessData(businessId) {
if(typeof getServerData().businesses[businessId] != null) {
@@ -930,53 +1170,53 @@ function getBusinessData(businessId) {
return false;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function doesBusinessHaveInterior(businessId) {
return getBusinessData(businessId).hasInterior;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function deleteBusinessEntrancePickup(businessId) {
if(getBusinessData(businessId).entrancePickup != null) {
//removeFromWorld(getBusinessData(businessId).entrancePickup);
- destroyElement(getBusinessData(businessId).entrancePickup);
- getBusinessData(businessId).entrancePickup = false;
+ deleteGameElement(getBusinessData(businessId).entrancePickup);
+ getBusinessData(businessId).entrancePickup = null;
}
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function deleteBusinessExitPickup(businessId) {
if(getBusinessData(businessId).exitPickup != null) {
//removeFromWorld(getBusinessData(businessId).exitPickup);
- destroyElement(getBusinessData(businessId).exitPickup);
- getBusinessData(businessId).exitPickup = false;
+ deleteGameElement(getBusinessData(businessId).exitPickup);
+ getBusinessData(businessId).exitPickup = null;
}
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function deleteBusinessEntranceBlip(businessId) {
if(getBusinessData(businessId).entranceBlip != null) {
//removeFromWorld(getBusinessData(businessId).entranceBlip);
- destroyElement(getBusinessData(businessId).entranceBlip);
- getBusinessData(businessId).entranceBlip = false;
+ deleteGameElement(getBusinessData(businessId).entranceBlip);
+ getBusinessData(businessId).entranceBlip = null;
}
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function deleteBusinessExitBlip(businessId) {
if(getBusinessData(businessId).exitBlip != null) {
//removeFromWorld(getBusinessData(businessId).exitBlip);
- destroyElement(getBusinessData(businessId).exitBlip);
- getBusinessData(businessId).exitBlip = false;
+ deleteGameElement(getBusinessData(businessId).exitBlip);
+ getBusinessData(businessId).exitBlip = null;
}
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function reloadAllBusinessesCommand(command, params, client) {
let clients = getClients();
@@ -1002,7 +1242,7 @@ function reloadAllBusinessesCommand(command, params, client) {
messageAdminAction(`All businesses have been reloaded by an admin!`);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function setAllBusinessIndexes() {
for(let i in getServerData().businesses) {
@@ -1010,7 +1250,7 @@ function setAllBusinessIndexes() {
}
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function addToBusinessInventory(businessId, itemType, amount, buyPrice) {
let tempItemData = new serverClasses.itemData(false);
@@ -1028,66 +1268,149 @@ function addToBusinessInventory(businessId, itemType, amount, buyPrice) {
getServerData().items[index].index = index;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function buyFromBusinessCommand(command, params, client) {
+ let businessId = (isPlayerInAnyBusiness(client)) ? getPlayerBusiness(client) : getClosestBusinessEntrance(getPlayerPosition(client));
+ if(areParamsEmpty(params)) {
+ showBusinessFloorInventoryToPlayer(client, businessId);
+ messagePlayerSyntax(client, getCommandSyntaxText(command));
+ return false;
+ }
+
+ let splitParams = params.split(" ");
+
+ if(!getBusinessData(businessId)) {
+ messagePlayerError(client, "Business not found!");
+ return false;
+ }
+
+ if(getBusinessData(businessId).locked) {
+ messagePlayerError(client, `This business is closed!`);
+ return false;
+ }
+
+ if(getBusinessData(businessId).hasInterior) {
+ if(!getPlayerBusiness(client)) {
+ if(doesPlayerHaveKeyBindForCommand(client, "enter")) {
+ messagePlayerTip(client, `You need to enter the business first! Press [#AAAAAA]${sdl.getKeyName(getPlayerKeyBindForCommand(client, "enter").key)} [#FFFFFF]to enter and exit a business`);
+ } else {
+ messagePlayerNormal(client, `You need to enter the business first! Use /enter to enter and exit a business`);
+ }
+ return false;
+ }
+ }
+
+ let itemSlot = toInteger(splitParams[0]) || 1;
+
+ if(typeof getBusinessData(businessId).floorItemCache[itemSlot-1] == "undefined") {
+ messagePlayerError(client, `Item slot ${itemSlot} doesn't exist!`);
+ return false;
+ }
+
+ if(getBusinessData(businessId).floorItemCache[itemSlot-1] == -1) {
+ messagePlayerError(client, `Item slot ${itemSlot} slot is empty!`);
+ return false;
+ }
+
+ let amount = 1;
+ if(areThereEnoughParams(params, 2, " ")) {
+ amount = toInteger(splitParams[1]) || 1;
+ if(amount <= 0) {
+ messagePlayerError(client, "The amount must be more than 0!");
+ return false;
+ }
+ }
+
+ if(getPlayerCurrentSubAccount(client).cash < getBusinessData(businessId).floorItemCache[itemSlot-1].buyPrice*amount) {
+ messagePlayerError(client, `You don't have enough money! You need [#AAAAAA]${getBusinessData(businessId).floorItemCache[itemSlot-1].buyPrice*amount-getPlayerCurrentSubAccount(client).cash} [#FFFFFF]more!`);
+ return false;
+ }
+
+ if(getItemData(getBusinessData(businessId).floorItemCache[itemSlot-1]).amount < amount) {
+ messagePlayerError(client, `There are only ${getItemData(getBusinessData(businessId).floorItemCache[itemSlot-1]).amount} ${getItemTypeData(getItemData(getBusinessData(businessId).floorItemCache[itemSlot-1]).itemTypeIndex).name} in slot ${itemSlot-1}`);
+ return false;
+ }
+
+ let firstSlot = getPlayerFirstEmptyHotBarSlot(client);
+ if(firstSlot == -1) {
+ messagePlayerError(client, `You don't have any space to carry this (full inventory)!`);
+ return false;
+ }
+
+ let totalCost = getItemData(getBusinessData(businessId).floorItemCache[itemSlot-1]).buyPrice*amount;
+ let individualCost = getItemData(getBusinessData(businessId).floorItemCache[itemSlot-1]).buyPrice;
+ let itemName = getItemTypeData(getItemData(getBusinessData(businessId).floorItemCache[itemSlot-1]).itemTypeIndex).name;
+ let priceEach = (amount > 1) ? `($${individualCost} each)` : ``;
+
+ takePlayerCash(client, totalCost);
+ createItem(getItemData(getBusinessData(businessId).floorItemCache[itemSlot-1]).itemTypeIndex, getItemData(getBusinessData(businessId).floorItemCache[itemSlot-1]).value, AG_ITEM_OWNER_PLAYER, getPlayerCurrentSubAccount(client).databaseId, amount);
+ cachePlayerHotBarItems(client);
+ getBusinessData(businessId).till = getBusinessData(businessId).till + totalCost;
+
+ getItemData(getBusinessData(businessId).floorItemCache[itemSlot-1]).amount = getItemData(getBusinessData(businessId).floorItemCache[itemSlot-1]).amount - amount;
+ if(getItemData(getBusinessData(businessId).floorItemCache[itemSlot-1]).amount == 0) {
+ destroyItem(getBusinessData(businessId).floorItemCache[itemSlot-1]);
+ }
+
+ messagePlayerSuccess(client, `You bought ${amount} [#AAAAAA]${itemName} [#FFFFFF]for ${totalCost} ${priceEach}`);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function setBusinessItemSellPriceCommand(command, params, client) {
let splitParams = params.split(" ");
let businessId = getBusinessFromParams(splitParams[2]) || (isPlayerInAnyBusiness(client)) ? getPlayerBusiness(client) : getClosestBusinessEntrance(getPlayerPosition(client));
if(!getBusinessData(businessId)) {
- messagePlayerError("Business not found!");
+ messagePlayerError(client, "Business not found!");
return false;
}
let itemSlot = toInteger(splitParams[0]) || 0;
- if(typeof getBusinessData(businessId).floorItemCache[itemSlot] == "undefined") {
- messagePlayerError(client, `Item slot ${itemSlot} doesn't exist!`);
+ if(typeof getBusinessData(businessId).floorItemCache[itemSlot-1] == "undefined") {
+ messagePlayerError(client, `Item slot ${itemSlot-1} doesn't exist!`);
return false;
}
- if(getBusinessData(businessId).floorItemCache[itemSlot] == -1) {
- messagePlayerError(client, `Item slot ${itemSlot} slot is empty!`);
+ if(getBusinessData(businessId).floorItemCache[itemSlot-1] == -1) {
+ messagePlayerError(client, `Item slot ${itemSlot-1} slot is empty!`);
return false;
}
- let newPrice = toInteger(splitParams[1]) || 0;
+ let oldPrice = getBusinessData(businessId).floorItemCache[itemSlot-1].buyPrice;
+ let newPrice = toInteger(splitParams[1]) || oldPrice;
if(newPrice < 0) {
- messagePlayerError("The price can't be negative!");
+ messagePlayerError(client, "The price can't be negative!");
return false;
}
- let oldPrice = getBusinessData(businessId).floorItemCache[itemSlot].buyPrice;
- getItemData(getBusinessData(businessId).floorItemCache[itemSlot]).buyPrice = newPrice;
+ getItemData(getBusinessData(businessId).floorItemCache[itemSlot-1]).buyPrice = newPrice;
- messagePlayerSuccess(client, `You changed the price of the ${getItemTypeData(getItemData(getBusinessData(businessId).floorItemCache[itemSlot])).name}s in slot ${itemSlot} from $${oldPrice} to $${newPrice}`);
+ messagePlayerSuccess(client, `You changed the price of the [#AAAAAA]${getItemTypeData(getItemData(getBusinessData(businessId).floorItemCache[itemSlot-1]).itemTypeIndex).name}'s [#FFFFFF]in slot [#AAAAAA]${itemSlot} [#FFFFFF]from $${oldPrice} to $${newPrice}`);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function storeItemInBusinessStorageCommand(command, params, client) {
let splitParams = params.split(" ");
let businessId = getBusinessFromParams(splitParams[2]) || (isPlayerInAnyBusiness(client)) ? getPlayerBusiness(client) : getClosestBusinessEntrance(getPlayerPosition(client));
if(!getBusinessData(businessId)) {
- messagePlayerError("Business not found!");
+ messagePlayerError(client, "Business not found!");
return false;
}
let itemSlot = toInteger(splitParams[0]) || 0;
- if(typeof getBusinessData(businessId).floorItemCache[itemSlot] == "undefined") {
+ if(typeof getBusinessData(businessId).floorItemCache[itemSlot-1] == "undefined") {
messagePlayerError(client, `Item slot ${itemSlot} doesn't exist!`);
return false;
}
- if(getBusinessData(businessId).floorItemCache[itemSlot] == -1) {
+ if(getBusinessData(businessId).floorItemCache[itemSlot-1] == -1) {
messagePlayerError(client, `Item slot ${itemSlot} slot is empty!`);
return false;
}
@@ -1099,31 +1422,31 @@ function storeItemInBusinessStorageCommand(command, params, client) {
return false;
}
- getItemData(getBusinessData(businessId).floorItemCache[itemSlot]).ownerType = AG_ITEM_OWNER_BIZSTORAGE;
- getBusinessData(businessId).storageItemCache[firstSlot] = getBusinessData(businessId).floorItemCache[itemSlot];
- getBusinessData(businessId).storageItemCache[itemSlot] = -1;
- messagePlayerSuccess(client, `You moved the ${getItemTypeData(getItemData(getBusinessData(businessId).storageItemCache[firstSlot])).name}s in slot ${itemSlot} to the business storage in slot ${firstSlot}`);
+ getItemData(getBusinessData(businessId).floorItemCache[itemSlot-1]).ownerType = AG_ITEM_OWNER_BIZSTORAGE;
+ getBusinessData(businessId).storageItemCache[firstSlot] = getBusinessData(businessId).floorItemCache[itemSlot-1];
+ getBusinessData(businessId).storageItemCache[itemSlot-1] = -1;
+ messagePlayerSuccess(client, `You moved the ${getItemTypeData(getItemData(getBusinessData(businessId).storageItemCache[firstSlot]).itemTypeIndex).name}s in slot ${itemSlot} to the business storage in slot ${firstSlot}`);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function stockItemOnBusinessFloorCommand(command, params, client) {
let splitParams = params.split(" ");
- let businessId = getBusinessFromParams(splitParams[2]) || (isPlayerInAnyBusiness(client)) ? getPlayerBusiness(client) : getClosestBusinessEntrance(getPlayerPosition(client));
+ let businessId = (isPlayerInAnyBusiness(client)) ? getPlayerBusiness(client) : getClosestBusinessEntrance(getPlayerPosition(client));
if(!getBusinessData(businessId)) {
- messagePlayerError("Business not found!");
+ messagePlayerError(client, "Business not found!");
return false;
}
let itemSlot = toInteger(splitParams[0]) || 0;
- if(typeof getBusinessData(businessId).storageItemCache[itemSlot] == "undefined") {
+ if(typeof getBusinessData(businessId).storageItemCache[itemSlot-1] == "undefined") {
messagePlayerError(client, `Item slot ${itemSlot} doesn't exist!`);
return false;
}
- if(getBusinessData(businessId).storageItemCache[itemSlot] == -1) {
+ if(getBusinessData(businessId).storageItemCache[itemSlot-1] == -1) {
messagePlayerError(client, `Item slot ${itemSlot} slot is empty!`);
return false;
}
@@ -1135,13 +1458,13 @@ function stockItemOnBusinessFloorCommand(command, params, client) {
return false;
}
- getItemData(getBusinessData(businessId).storageItemCache[itemSlot]).ownerType = AG_ITEM_OWNER_BIZFLOOR;
- getBusinessData(businessId).floorItemCache[firstSlot] = getBusinessData(businessId).storageItemCache[itemSlot];
- getBusinessData(businessId).storageItemCache[itemSlot] = -1;
- messagePlayerSuccess(client, `You moved the ${getItemTypeData(getItemData(getBusinessData(businessId).storageItemCache[firstSlot])).name}s in slot ${itemSlot} of the business storage to the business floor slot ${firstSlot}`);
+ getItemData(getBusinessData(businessId).storageItemCache[itemSlot-1]).ownerType = AG_ITEM_OWNER_BIZFLOOR;
+ getBusinessData(businessId).floorItemCache[firstSlot] = getBusinessData(businessId).storageItemCache[itemSlot-1];
+ getBusinessData(businessId).storageItemCache[itemSlot-1] = -1;
+ messagePlayerSuccess(client, `You moved the ${getItemTypeData(getItemData(getBusinessData(businessId).storageItemCache[firstSlot]).itemTypeIndex).name}s in slot ${itemSlot} of the business storage to the business floor slot ${firstSlot}`);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function getBusinessStorageFirstFreeItemSlot(businessId) {
for(let i in getBusinessData(businessId).storageItemCache) {
@@ -1153,7 +1476,7 @@ function getBusinessStorageFirstFreeItemSlot(businessId) {
return -1;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function getBusinessFloorFirstFreeItemSlot(businessId) {
for(let i in getBusinessData(businessId).floorItemCache) {
@@ -1165,4 +1488,63 @@ function getBusinessFloorFirstFreeItemSlot(businessId) {
return -1;
}
-// ---------------------------------------------------------------------------
\ No newline at end of file
+// ===========================================================================
+
+function cacheAllBusinessItems() {
+ logToConsole(LOG_DEBUG, "[Asshat.Business] Caching all business items ...");
+ for(let i in getServerData().businesses) {
+ cacheBusinessItems(i);
+ }
+ logToConsole(LOG_DEBUG, "[Asshat.Business] Cached all business items successfully!");
+}
+
+// ===========================================================================
+
+function cacheBusinessItems(businessId) {
+ getBusinessData(businessId).floorItemCache = [];
+ getBusinessData(businessId).storageItemCache = [];
+
+ logToConsole(LOG_VERBOSE, `[Asshat.Business] Caching business items for business ${businessId} (${getBusinessData(businessId).name}) ...`);
+ for(let i in getServerData().items) {
+ if(getItemData(i).ownerType == AG_ITEM_OWNER_BIZFLOOR && getItemData(i).ownerId == getBusinessData(businessId).databaseId) {
+ getBusinessData(businessId).floorItemCache.push(i);
+ } else if(getItemData(i).ownerType == AG_ITEM_OWNER_BIZSTORAGE && getItemData(i).ownerId == getBusinessData(businessId).databaseId) {
+ getBusinessData(businessId).storageItemCache.push(i);
+ }
+ }
+ logToConsole(LOG_VERBOSE, `[Asshat.Business] Successfully cached ${getBusinessData(businessId).floorItemCache.length} floor items and ${getBusinessData(businessId).storageItemCache} storage items for business ${businessId} (${getBusinessData(businessId).name})!`);
+}
+
+// ===========================================================================
+
+function getHouseIdFromDatabaseId(databaseId) {
+ for(let i in getServerData().businesses) {
+ if(getBusinessData(i).databaseId == databaseId) {
+ return i;
+ }
+ }
+
+ return false;
+}
+
+// ===========================================================================
+
+function updateBusinessPickupLabelData(businessId) {
+ setEntityData(getBusinessData(businessId).entrancePickup, "ag.owner.type", AG_PICKUP_BUSINESS_ENTRANCE, false);
+ setEntityData(getBusinessData(businessId).entrancePickup, "ag.owner.id", businessId, false);
+ setEntityData(getBusinessData(businessId).entrancePickup, "ag.label.type", AG_LABEL_BUSINESS, true);
+ setEntityData(getBusinessData(businessId).entrancePickup, "ag.label.name", getBusinessData(businessId).name, true);
+ setEntityData(getBusinessData(businessId).entrancePickup, "ag.label.locked", getBusinessData(businessId).locked, true);
+ if(getBusinessData(businessId).floorItemCache.length > 0) {
+ setEntityData(getBusinessData(businessId).entrancePickup, "ag.label.buyhelp", true, true);
+ }
+ if(getBusinessData(businessId).buyPrice > 0) {
+ setEntityData(getBusinessData(businessId).entrancePickup, "ag.label.price", getBusinessData(businessId).buyPrice, true);
+ }
+
+ setEntityData(getBusinessData(businessId).exitPickup, "ag.owner.type", AG_PICKUP_BUSINESS_EXIT, false);
+ setEntityData(getBusinessData(businessId).exitPickup, "ag.owner.id", businessId, false);
+ setEntityData(getBusinessData(businessId).exitPickup, "ag.label.type", AG_LABEL_EXIT, true);
+}
+
+// ===========================================================================
\ No newline at end of file
diff --git a/scripts/server/business/bakery.js b/scripts/server/business/bakery.js
index 7be06872..81c4f5f6 100644
--- a/scripts/server/business/bakery.js
+++ b/scripts/server/business/bakery.js
@@ -2,7 +2,7 @@
// Asshat-Gaming Roleplay
// https://github.com/VortrexFTW/gtac_asshat_rp
// Copyright (c) 2021 Asshat-Gaming (https://asshatgaming.com)
-// ---------------------------------------------------------------------------
+// ===========================================================================
// FILE: bakery.js
// DESC: Provides bakery business functions and usage
// TYPE: Business (JavaScript)
diff --git a/scripts/server/business/bar.js b/scripts/server/business/bar.js
index 714ff50c..f7704cf1 100644
--- a/scripts/server/business/bar.js
+++ b/scripts/server/business/bar.js
@@ -2,7 +2,7 @@
// Asshat-Gaming Roleplay
// https://github.com/VortrexFTW/gtac_asshat_rp
// Copyright (c) 2021 Asshat-Gaming (https://asshatgaming.com)
-// ---------------------------------------------------------------------------
+// ===========================================================================
// FILE: bar.js
// DESC: Provides bar/pub business functions and usage
// TYPE: Business (JavaScript)
diff --git a/scripts/server/business/burger.js b/scripts/server/business/burger.js
index b8fd1a6a..0953ae3e 100644
--- a/scripts/server/business/burger.js
+++ b/scripts/server/business/burger.js
@@ -2,7 +2,7 @@
// Asshat-Gaming Roleplay
// https://github.com/VortrexFTW/gtac_asshat_rp
// Copyright (c) 2021 Asshat-Gaming (https://asshatgaming.com)
-// ---------------------------------------------------------------------------
+// ===========================================================================
// FILE: burger.js
// DESC: Provides burger joint (McDonalds?) business functions and usage
// TYPE: Business (JavaScript)
diff --git a/scripts/server/business/clothing.js b/scripts/server/business/clothing.js
index cccbd96d..ed94081c 100644
--- a/scripts/server/business/clothing.js
+++ b/scripts/server/business/clothing.js
@@ -2,7 +2,7 @@
// Asshat-Gaming Roleplay
// https://github.com/VortrexFTW/gtac_asshat_rp
// Copyright (c) 2021 Asshat-Gaming (https://asshatgaming.com)
-// ---------------------------------------------------------------------------
+// ===========================================================================
// FILE: clothing.js
// DESC: Provides clothing (skin) business functions and usage
// TYPE: Business (JavaScript)
diff --git a/scripts/server/business/club.js b/scripts/server/business/club.js
index 942305ee..5dd2724e 100644
--- a/scripts/server/business/club.js
+++ b/scripts/server/business/club.js
@@ -2,7 +2,7 @@
// Asshat-Gaming Roleplay
// https://github.com/VortrexFTW/gtac_asshat_rp
// Copyright (c) 2021 Asshat-Gaming (https://asshatgaming.com)
-// ---------------------------------------------------------------------------
+// ===========================================================================
// FILE: club.js
// DESC: Provides club/nightclub business functions and usage
// TYPE: Business (JavaScript)
diff --git a/scripts/server/business/fuel.js b/scripts/server/business/fuel.js
index fb7ce59d..6eaceb5a 100644
--- a/scripts/server/business/fuel.js
+++ b/scripts/server/business/fuel.js
@@ -2,7 +2,7 @@
// Asshat-Gaming Roleplay
// https://github.com/VortrexFTW/gtac_asshat_rp
// Copyright (c) 2021 Asshat-Gaming (https://asshatgaming.com)
-// ---------------------------------------------------------------------------
+// ===========================================================================
// FILE: fuel.js
// DESC: Provides fuel/petrol business functions and usage
// TYPE: Business (JavaScript)
diff --git a/scripts/server/business/mechanic.js b/scripts/server/business/mechanic.js
index a5d1f4f3..bc71fb4f 100644
--- a/scripts/server/business/mechanic.js
+++ b/scripts/server/business/mechanic.js
@@ -2,7 +2,7 @@
// Asshat-Gaming Roleplay
// https://github.com/VortrexFTW/gtac_asshat_rp
// Copyright (c) 2021 Asshat-Gaming (https://asshatgaming.com)
-// ---------------------------------------------------------------------------
+// ===========================================================================
// FILE: mechanic.js
// DESC: Provides mechanic/vehicle repair business functions and usage
// TYPE: Business (JavaScript)
diff --git a/scripts/server/business/pizza.js b/scripts/server/business/pizza.js
index 5c3d5540..3e15c306 100644
--- a/scripts/server/business/pizza.js
+++ b/scripts/server/business/pizza.js
@@ -2,7 +2,7 @@
// Asshat-Gaming Roleplay
// https://github.com/VortrexFTW/gtac_asshat_rp
// Copyright (c) 2021 Asshat-Gaming (https://asshatgaming.com)
-// ---------------------------------------------------------------------------
+// ===========================================================================
// FILE: pizza.js
// DESC: Provides pizza restaurant business functions and usage
// TYPE: Business (JavaScript)
diff --git a/scripts/server/business/restaurant.js b/scripts/server/business/restaurant.js
index 312b3309..bcc6f8c8 100644
--- a/scripts/server/business/restaurant.js
+++ b/scripts/server/business/restaurant.js
@@ -2,7 +2,7 @@
// Asshat-Gaming Roleplay
// https://github.com/VortrexFTW/gtac_asshat_rp
// Copyright (c) 2021 Asshat-Gaming (https://asshatgaming.com)
-// ---------------------------------------------------------------------------
+// ===========================================================================
// FILE: restaurant.js
// DESC: Provides generic restaurant business functions and usage
// TYPE: Business (JavaScript)
diff --git a/scripts/server/business/vehicle.js b/scripts/server/business/vehicle.js
index 737deda3..131db0d9 100644
--- a/scripts/server/business/vehicle.js
+++ b/scripts/server/business/vehicle.js
@@ -2,7 +2,7 @@
// Asshat-Gaming Roleplay
// https://github.com/VortrexFTW/gtac_asshat_rp
// Copyright (c) 2021 Asshat-Gaming (https://asshatgaming.com)
-// ---------------------------------------------------------------------------
+// ===========================================================================
// FILE: vehicle.js
// DESC: Provides vehicle dealership business functions and usage
// TYPE: Business (JavaScript)
diff --git a/scripts/server/business/weapon.js b/scripts/server/business/weapon.js
index e6e3145c..4af40c85 100644
--- a/scripts/server/business/weapon.js
+++ b/scripts/server/business/weapon.js
@@ -2,8 +2,9 @@
// Asshat-Gaming Roleplay
// https://github.com/VortrexFTW/gtac_asshat_rp
// Copyright (c) 2021 Asshat-Gaming (https://asshatgaming.com)
-// ---------------------------------------------------------------------------
+// ===========================================================================
// FILE: weapon.js
-// DESC: Provides weapon (ammu) business functions and usage
+// DESC: Provides weapon (ammunations & illegal gunshops) business usage
// TYPE: Business (JavaScript)
-// ===========================================================================
\ No newline at end of file
+// ===========================================================================
+
diff --git a/scripts/server/chat.js b/scripts/server/chat.js
index 46d9b8e6..5dde8cab 100644
--- a/scripts/server/chat.js
+++ b/scripts/server/chat.js
@@ -2,19 +2,19 @@
// Asshat-Gaming Roleplay
// https://github.com/VortrexFTW/gtac_asshat_rp
// Copyright (c) 2021 Asshat-Gaming (https://asshatgaming.com)
-// ---------------------------------------------------------------------------
+// ===========================================================================
// FILE: chat.js
// DESC: Provides chat functions and usage
// TYPE: Server (JavaScript)
// ===========================================================================
function initChatScript() {
- logToConsole(LOG_DEBUG, "[Asshat.Chat]: Initializing chat script ...");
- logToConsole(LOG_DEBUG, "[Asshat.Chat]: Chat script initialized successfully!");
+ logToConsole(LOG_INFO, "[Asshat.Chat]: Initializing chat script ...");
+ logToConsole(LOG_INFO, "[Asshat.Chat]: Chat script initialized successfully!");
return true;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function meActionCommand(command, params, client) {
if(areParamsEmpty(params)) {
@@ -26,9 +26,14 @@ function meActionCommand(command, params, client) {
return true;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function doActionCommand(command, params, client) {
+ if(isPlayerMuted(client)) {
+ messagePlayerError(client, "You are muted and can't chat!");
+ return false;
+ }
+
if(areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
@@ -38,9 +43,14 @@ function doActionCommand(command, params, client) {
return true;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function shoutCommand(command, params, client) {
+ if(isPlayerMuted(client)) {
+ messagePlayerError(client, "You are muted and can't chat!");
+ return false;
+ }
+
if(areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
@@ -50,9 +60,14 @@ function shoutCommand(command, params, client) {
return true;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function talkCommand(command, params, client) {
+ if(isPlayerMuted(client)) {
+ messagePlayerError(client, "You are muted and can't chat!");
+ return false;
+ }
+
if(areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
@@ -62,9 +77,14 @@ function talkCommand(command, params, client) {
return true;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function whisperCommand(command, params, client) {
+ if(isPlayerMuted(client)) {
+ messagePlayerError(client, "You are muted and can't chat!");
+ return false;
+ }
+
if(areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
@@ -74,9 +94,14 @@ function whisperCommand(command, params, client) {
return true;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function adminChatCommand(command, params, client) {
+ if(isPlayerMuted(client)) {
+ messagePlayerError(client, "You are muted and can't chat!");
+ return false;
+ }
+
if(areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
@@ -85,9 +110,14 @@ function adminChatCommand(command, params, client) {
messageAdmins(`[#FFFF00][Admin Chat] [#AAAAAA]${client.name} [#CCCCCC](${getPlayerStaffTitle(client)})[#FFFFFF]: ${params}`);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function clanChatCommand(command, params, client) {
+ if(isPlayerMuted(client)) {
+ messagePlayerError(client, "You are muted and can't chat!");
+ return false;
+ }
+
if(areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
@@ -96,18 +126,18 @@ function clanChatCommand(command, params, client) {
clanChat(client, params);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function talkToNearbyPlayers(client, messageText) {
let clients = getClientsInRange(getPlayerPosition(client), getGlobalConfig().talkDistance);
for(let i in clients) {
//if(clients[i] != client) {
- messagePlayerTalk(getClientFromPlayerElement(clients[i]), client, messageText);
+ messagePlayerTalk(clients[i], client, messageText);
//}
}
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function phoneOutgoingToNearbyPlayers(client, messageText) {
let clients = getClientsInRange(getPlayerPosition(client), getGlobalConfig().talkDistance);
@@ -116,7 +146,7 @@ function phoneOutgoingToNearbyPlayers(client, messageText) {
}
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function phoneIncomingToNearbyPlayers(client, messageText) {
let clients = getClientsInRange(getPlayerPosition(client), getGlobalConfig().radioSpeakerDistance);
@@ -125,59 +155,59 @@ function phoneIncomingToNearbyPlayers(client, messageText) {
}
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function whisperToNearbyPlayers(client, messageText) {
- let clients = getClientsInRange(client.player.position, getGlobalConfig().talkDistance);
+ let clients = getClientsInRange(getPlayerPosition(client), getGlobalConfig().talkDistance);
for(let i in clients) {
//if(clients[i] != client) {
- messagePlayerWhisper(getClientFromPlayerElement(clients[i]), client, messageText);
+ messagePlayerWhisper(clients[i], client, messageText);
//}
}
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function shoutToNearbyPlayers(client, messageText) {
- let clients = getClientsInRange(client.player.position, getGlobalConfig().shoutDistance);
+ let clients = getClientsInRange(getPlayerPosition(client), getGlobalConfig().shoutDistance);
for(let i in clients) {
//if(clients[i].index != client.index) {
- messagePlayerShout(getClientFromPlayerElement(clients[i]), client, messageText);
+ messagePlayerShout(clients[i], client, messageText);
//}
}
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function doActionToNearbyPlayers(client, messageText) {
- let clients = getClientsInRange(client.player.position, getGlobalConfig().doActionDistance);
+ let clients = getClientsInRange(getPlayerPosition(client), getGlobalConfig().doActionDistance);
for(let i in clients) {
//if(clients[i].index != client.index) {
- messagePlayerDoAction(getClientFromPlayerElement(clients[i]), client, messageText);
+ messagePlayerDoAction(clients[i], client, messageText);
//}
}
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function meActionToNearbyPlayers(client, messageText) {
- let clients = getClientsInRange(client.player.position, getGlobalConfig().meActionDistance);
+ let clients = getClientsInRange(getPlayerPosition(client), getGlobalConfig().meActionDistance);
for(let i in clients) {
//if(clients[i].index != client.index) {
- messagePlayerMeAction(getClientFromPlayerElement(clients[i]), client, messageText);
+ messagePlayerMeAction(clients[i], client, messageText);
//}
}
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function clanChat(client, messageText) {
let clients = getClients();
for(let i in clients) {
if(getPlayerCurrentSubAccount(client).clan != getPlayerCurrentSubAccount(clients[i]).clan) {
- messageClientClanChat(getClientFromPlayerElement(clients[i]), client, messageText);
+ messageClientClanChat(clients[i], client, messageText);
}
}
}
-// ---------------------------------------------------------------------------
\ No newline at end of file
+// ===========================================================================
\ No newline at end of file
diff --git a/scripts/server/clan.js b/scripts/server/clan.js
index ef193e47..49dc6e74 100644
--- a/scripts/server/clan.js
+++ b/scripts/server/clan.js
@@ -2,24 +2,24 @@
// Asshat-Gaming Roleplay
// https://github.com/VortrexFTW/gtac_asshat_rp
// Copyright (c) 2021 Asshat-Gaming (https://asshatgaming.com)
-// ---------------------------------------------------------------------------
+// ===========================================================================
// FILE: clan.js
// DESC: Provides clan functions and usage
// TYPE: Server (JavaScript)
// ===========================================================================
function initClanScript() {
- logToConsole(LOG_DEBUG, "[Asshat.Clan]: Initializing clans script ...");
+ logToConsole(LOG_INFO, "[Asshat.Clan]: Initializing clans script ...");
getServerData().clans = loadClansFromDatabase();
setAllClanDataIndexes();
- logToConsole(LOG_DEBUG, "[Asshat.Clan]: Clan script initialized successfully!");
+ logToConsole(LOG_INFO, "[Asshat.Clan]: Clan script initialized successfully!");
return true;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function loadClansFromDatabase() {
- logToConsole(LOG_DEBUG, "[Asshat.Clan]: Loading clans from database ...");
+ logToConsole(LOG_INFO, "[Asshat.Clan]: Loading clans from database ...");
let tempClans = [];
let dbConnection = connectToDatabase();
@@ -30,11 +30,11 @@ function loadClansFromDatabase() {
if(dbQuery) {
if(dbQuery.numRows > 0) {
while(dbAssoc = fetchQueryAssoc(dbQuery)) {
- let tempClanData = getClasses().clanData(dbAssoc);
+ let tempClanData = new serverClasses.clanData(dbAssoc);
tempClanData.members = loadClanMembersFromDatabase(tempClanData.databaseId);
tempClanData.ranks = loadClanRanksFromDatabase(tempClanData.databaseId);
tempClans.push(tempClanData);
- logToConsole(LOG_DEBUG, `[Asshat.Clan]: Clan '${tempClanData.name}' loaded from database successfully!`);
+ logToConsole(LOG_VERBOSE, `[Asshat.Clan]: Clan '${tempClanData.name}' loaded from database successfully!`);
}
}
freeDatabaseQuery(dbQuery);
@@ -42,11 +42,95 @@ function loadClansFromDatabase() {
disconnectFromDatabase(dbConnection);
}
- logToConsole(LOG_DEBUG, `[Asshat.Clan]: ${tempClans.length} clans loaded from database successfully!`);
+ logToConsole(LOG_INFO, `[Asshat.Clan]: ${tempClans.length} clans loaded from database successfully!`);
return tempClans;
}
-// -------------------------------------------------------------------------
+// ===========================================================================
+
+function loadClanMembersFromDatabase() {
+ logToConsole(LOG_INFO, "[Asshat.Clan]: Loading clans from database ...");
+
+ let tempClans = [];
+ let dbConnection = connectToDatabase();
+ let dbAssoc;
+
+ if(dbConnection) {
+ let dbQuery = queryDatabase(dbConnection, `SELECT * FROM clan_main WHERE clan_deleted = 0 AND clan_server = ${getServerId()}`);
+ if(dbQuery) {
+ if(dbQuery.numRows > 0) {
+ while(dbAssoc = fetchQueryAssoc(dbQuery)) {
+ let tempClanData = new serverClasses.clanData(dbAssoc);
+ tempClanData.members = loadClanMembersFromDatabase(tempClanData.databaseId);
+ tempClanData.ranks = loadClanRanksFromDatabase(tempClanData.databaseId);
+ tempClans.push(tempClanData);
+ logToConsole(LOG_VERBOSE, `[Asshat.Clan]: Clan '${tempClanData.name}' loaded from database successfully!`);
+ }
+ }
+ freeDatabaseQuery(dbQuery);
+ }
+ disconnectFromDatabase(dbConnection);
+ }
+
+ logToConsole(LOG_INFO, `[Asshat.Clan]: ${tempClans.length} clans loaded from database successfully!`);
+ return tempClans;
+}
+
+// ===========================================================================
+
+function loadClanRanksFromDatabase(clanDatabaseId) {
+ logToConsole(LOG_INFO, `[Asshat.Clan]: Loading ranks for clan ${clanDatabaseId} from database ...`);
+
+ let dbConnection = connectToDatabase();
+ let dbAssoc;
+ let tempClanRanks = [];
+
+ if(dbConnection) {
+ let dbQuery = queryDatabase(dbConnection, `SELECT * FROM clan_rank WHERE clan_rank_clan = ${clanDatabaseId}`);
+ if(dbQuery) {
+ if(dbQuery.numRows > 0) {
+ let dbAssoc = fetchQueryAssoc(dbQuery)
+ let tempClanRankData = new serverClasses.clanRankData(dbAssoc);
+ tempClanRanks.push(tempClanRankData);
+ logToConsole(LOG_VERBOSE, `[Asshat.Clan]: Clan rank '${tempClanRankData.name}' loaded from database successfully!`);
+ }
+ freeDatabaseQuery(dbQuery);
+ }
+ disconnectFromDatabase(dbConnection);
+ }
+
+ logToConsole(LOG_INFO, `[Asshat.Clan]: Loaded ranks for clan ${clanDatabaseId} from database successfully!`);
+ return tempClanRanks;
+}
+
+// ===========================================================================
+
+function loadClanMembersFromDatabase(clanDatabaseId) {
+ logToConsole(LOG_INFO, `[Asshat.Clan]: Loading members for clan ${clanDatabaseId} from database ...`);
+
+ let dbConnection = connectToDatabase();
+ let dbAssoc;
+ let tempClanMembers = [];
+
+ if(dbConnection) {
+ let dbQuery = queryDatabase(dbConnection, `SELECT * FROM clan_member WHERE clan_member_clan = ${clanDatabaseId}`);
+ if(dbQuery) {
+ if(dbQuery.numRows > 0) {
+ let dbAssoc = fetchQueryAssoc(dbQuery)
+ let tempClanMemberData = new serverClasses.clanMemberData(dbAssoc);
+ tempClanMembers.push(tempClanMemberData);
+ logToConsole(LOG_VERBOSE, `[Asshat.Clan]: Clan member '${tempClanMemberData.subAccount}' loaded from database successfully!`);
+ }
+ freeDatabaseQuery(dbQuery);
+ }
+ disconnectFromDatabase(dbConnection);
+ }
+
+ logToConsole(LOG_INFO, `[Asshat.Clan]: Loaded members for clan ${clanDatabaseId} from database successfully!`);
+ return tempClanMembers;
+}
+
+// ===========================================================================
function createClanCommand(command, params, client) {
if(areParamsEmpty(params)) {
@@ -64,7 +148,7 @@ function createClanCommand(command, params, client) {
messageAdmins(`[#AAAAAA]${client.name} [#FFFFFF]created clan[#FF9900]${params}`);
}
-// -------------------------------------------------------------------------
+// ===========================================================================
function deleteClanCommand(command, params, client) {
if(areParamsEmpty(params)) {
@@ -83,7 +167,7 @@ function deleteClanCommand(command, params, client) {
deleteClan(clanId);
}
-// -------------------------------------------------------------------------
+// ===========================================================================
function setClanOwnerCommand(command, params, client) {
if(!doesPlayerHaveClanPermission(client, getClanFlagValue("owner"))) {
@@ -116,7 +200,7 @@ function setClanOwnerCommand(command, params, client) {
messageAdmins(`[#AAAAAA]${client.name} [#FFFFFF]set clan[#FF9900]${getClanData(clanId).name} [#FFFFFF]owner to [#AAAAAA]${getCharacterFullName(targetClient)}`);
}
-// -------------------------------------------------------------------------
+// ===========================================================================
function setClanTagCommand(command, params, client) {
if(!doesPlayerHaveClanPermission(client, getClanFlagValue("clanTag"))) {
@@ -141,7 +225,7 @@ function setClanTagCommand(command, params, client) {
messageAdmins(`[#AAAAAA]${client.name} [#FFFFFF]set clan[#FF9900]${getClanData(clanId).index} [#FFFFFF]tag to [#AAAAAA]${params}`);
}
-// -------------------------------------------------------------------------
+// ===========================================================================
function setClanNameCommand(command, params, client) {
if(!doesPlayerHaveClanPermission(client, getClanFlagValue("clanName"))) {
@@ -166,7 +250,7 @@ function setClanNameCommand(command, params, client) {
messageAdmins(`[#AAAAAA]${client.name} [#FFFFFF]set clan[#FF9900]${getClanData(clanId).index} [#FFFFFF]name to [#AAAAAA]${params}`);
}
-// -------------------------------------------------------------------------
+// ===========================================================================
function setClanMemberTagCommand(command, params, client) {
if(!doesPlayerHaveClanPermission(client, getClanFlagValue("memberTag"))) {
@@ -199,7 +283,7 @@ function setClanMemberTagCommand(command, params, client) {
messagePlayerAlert(client, `[#AAAAAA]${getCharacterFullName(targetClient)} [#FFFFFF]set your clan tag to [#AAAAAA]${tag}`);
}
-// -------------------------------------------------------------------------
+// ===========================================================================
function setClanRankTagCommand(command, params, client) {
if(!doesPlayerHaveClanPermission(client, getClanFlagValue("rankTag"))) {
@@ -229,7 +313,7 @@ function setClanRankTagCommand(command, params, client) {
}
}
-// -------------------------------------------------------------------------
+// ===========================================================================
function addClanMemberFlagCommand(command, params, client) {
if(!doesPlayerHaveClanPermission(client, getClanFlagValue("memberFlags"))) {
@@ -266,7 +350,7 @@ function addClanMemberFlagCommand(command, params, client) {
messagePlayerSuccess(client, `You added the [#AAAAAA]${splitParams[1]} [#FFFFFF]clan flag to [#AAAAAA]${getCharacterFullName(client)}`);
}
-// -------------------------------------------------------------------------
+// ===========================================================================
function removeClanMemberFlagCommand(command, params, client) {
if(!doesPlayerHaveClanPermission(client, getClanFlagValue("memberFlags"))) {
@@ -303,7 +387,7 @@ function removeClanMemberFlagCommand(command, params, client) {
messagePlayerSuccess(client, `You removed the [#AAAAAA]${splitParams[1]} [#FFFFFF]clan flag from [#AAAAAA]${getCharacterFullName(client)}`);
}
-// -------------------------------------------------------------------------
+// ===========================================================================
function addClanRankFlagCommand(command, params, client) {
if(!doesPlayerHaveClanPermission(client, getClanFlagValue("rankFlags"))) {
@@ -341,7 +425,7 @@ function addClanRankFlagCommand(command, params, client) {
messagePlayerSuccess(client, `You added the [#AAAAAA]${splitParams[1]} [#FFFFFF]clan flag to rank [#AAAAAA]${getClanRankData(clanId, rankId).name}`);
}
-// -------------------------------------------------------------------------
+// ===========================================================================
function removeClanRankFlagCommand(command, params, client) {
if(!doesPlayerHaveClanPermission(client, getClanFlagValue("rankFlags"))) {
@@ -379,7 +463,7 @@ function removeClanRankFlagCommand(command, params, client) {
messagePlayerSuccess(client, `You removed the [#AAAAAA]${splitParams[1]} [#FFFFFF]clan flag from rank [#AAAAAA]${getClanRankData(clanId, rankId).name}`);
}
-// -------------------------------------------------------------------------
+// ===========================================================================
function setClanMemberTitleCommand(command, params, client) {
if(!doesPlayerHaveClanPermission(client, getClanFlagValue("memberTitle"))) {
@@ -411,7 +495,7 @@ function setClanMemberTitleCommand(command, params, client) {
messagePlayerSuccess(client, `You changed the name of [#AAAAAA]${getCharacterFullName(client)} [#FFFFFF]from [#AAAAAA]${oldMemberTitle} [#FFFFFF]to [#AAAAAA]${params}`);
}
-// -------------------------------------------------------------------------
+// ===========================================================================
function setClanRankTitleCommand(command, params, client) {
if(!doesPlayerHaveClanPermission(client, getClanFlagValue("rankTitle"))) {
@@ -443,7 +527,7 @@ function setClanRankTitleCommand(command, params, client) {
messagePlayerSuccess(client, `You changed the name of rank ${rankId} from [#AAAAAA]${oldRankName} [#FFFFFF]to [#AAAAAA]${params}`);
}
-// -------------------------------------------------------------------------
+// ===========================================================================
function createClan(name) {
let dbConnection = connectToDatabase();
@@ -451,19 +535,18 @@ function createClan(name) {
if(dbConnection) {
escapedName = escapeDatabaseString(dbConnection, escapedName)
- let dbQuery = queryDatabase(dbConnection, `INSERT INTO clan_main (clan_server, clan_name) VALUES (${getServerId()}, '${escapedName}')`);
- disconnectFromDatabase(dbConnection);
+ queryDatabase(dbConnection, `INSERT INTO clan_main (clan_server, clan_name) VALUES (${getServerId()}, '${escapedName}')`);
+ let tempClan = new serverClasses.clanData();
+ tempClan.databaseId = getDatabaseInsertId(dbConnection);
+ tempClan.name = name;
+ getServerData().clans.push(tempClan);
- let tempClanData = loadClanFromDatabaseById(getDatabaseInsertId(dbConnection));
- if(tempClanData != false) {
- let tempClan = serverClasses.clanData(tempClanData);
- getServerData().clans.push(tempClan);
- }
+ setAllClanDataIndexes();
}
return true;
}
-// -------------------------------------------------------------------------
+// ===========================================================================
function deleteClan(clanId) {
saveClansToDatabase();
@@ -481,7 +564,7 @@ function deleteClan(clanId) {
return false;
}
-// -------------------------------------------------------------------------
+// ===========================================================================
function getClanData(clanId) {
let clans = getServerData().clans;
@@ -494,7 +577,7 @@ function getClanData(clanId) {
return false;
}
-// -------------------------------------------------------------------------
+// ===========================================================================
function doesClanNameExist(name) {
let clans = getServerData().clans;
@@ -507,7 +590,7 @@ function doesClanNameExist(name) {
return false;
}
-// -------------------------------------------------------------------------
+// ===========================================================================
function doesClanIdExist(clanId) {
let clans = getServerData().clans;
@@ -520,13 +603,13 @@ function doesClanIdExist(clanId) {
return false;
}
-// -------------------------------------------------------------------------
+// ===========================================================================
function reloadAllClans() {
getServerData().clans = loadClansFromDatabase();
}
-// -------------------------------------------------------------------------
+// ===========================================================================
function saveClansToDatabase() {
let clans = getServerData().clans;
@@ -535,12 +618,13 @@ function saveClansToDatabase() {
}
}
-// -------------------------------------------------------------------------
+// ===========================================================================
function saveClanToDatabase(clanData) {
let dbConnection = connectToDatabase();
if(dbConnection) {
- let dbQueryString = `UPDATE clan_main SET clan_name = '${escapeDatabaseString(dbConnection, clanData.name)}', clan_owner = ${clanData.ownerId}`;
+ let safeClanName = escapeDatabaseString(dbConnection, clanData.name);
+ let dbQueryString = `UPDATE clan_main SET clan_name = '${safeClanName}', clan_owner = ${clanData.ownerId} WHERE clan_id = ${clanData.databaseId}`;
let dbQuery = queryDatabase(dbConnection, dbQueryString);
freeDatabaseQuery(dbQuery);
disconnectFromDatabase(dbConnection);
@@ -550,55 +634,55 @@ function saveClanToDatabase(clanData) {
return false;
}
-// -------------------------------------------------------------------------
+// ===========================================================================
function setClanTag(clanId, tag) {
getClanData(clanId).tag = tag;
}
-// -------------------------------------------------------------------------
+// ===========================================================================
function setClanOwner(clanId, ownerId) {
getClanData(clanId).ownerId = ownerId;
}
-// -------------------------------------------------------------------------
+// ===========================================================================
function setClanMemberTag(memberId, tag) {
// finish this later, need to query db
}
-// -------------------------------------------------------------------------
+// ===========================================================================
function setClanMemberFlags(memberId, flags) {
// finish this later, need to query db
}
-// -------------------------------------------------------------------------
+// ===========================================================================
function setClanMemberTitle(memberId, title) {
// finish this later, need to query db
}
-// -------------------------------------------------------------------------
+// ===========================================================================
function setClanRankTag(clanId, rankId, tag) {
getClanRankData(clanId, rankId).tag = tag;
}
-// -------------------------------------------------------------------------
+// ===========================================================================
function setClanRankFlags(clanId, rankId, flags) {
getClanRankData(clanId, rankId).flags = flags;
}
-// -------------------------------------------------------------------------
+// ===========================================================================
function setClanRankTitle(clanId, rankId, title) {
getClanRankData(clanId, rankId).title = title;
}
-// -------------------------------------------------------------------------
+// ===========================================================================
function saveAllClansToDatabase() {
for(let i in getServerData().clans) {
@@ -606,7 +690,7 @@ function saveAllClansToDatabase() {
}
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function setAllClanDataIndexes() {
for(let i in getServerData().clans) {
@@ -624,7 +708,7 @@ function setAllClanDataIndexes() {
}
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function arePlayersInSameClan(client1, client2) {
if(getPlayerClan(client1) == getPlayerClan(client2)) {
@@ -634,4 +718,4 @@ function arePlayersInSameClan(client1, client2) {
return false;
}
-// ---------------------------------------------------------------------------
\ No newline at end of file
+// ===========================================================================
\ No newline at end of file
diff --git a/scripts/server/class.js b/scripts/server/class.js
index 7bbae37f..556b522d 100644
--- a/scripts/server/class.js
+++ b/scripts/server/class.js
@@ -2,20 +2,23 @@
// Asshat-Gaming Roleplay
// https://github.com/VortrexFTW/gtac_asshat_rp
// Copyright (c) 2021 Asshat-Gaming (https://asshatgaming.com)
-// ---------------------------------------------------------------------------
+// ===========================================================================
// FILE: class.js
// DESC: Provides classes
// TYPE: Server (JavaScript)
// ===========================================================================
-let serverClasses = initClassTable();
+let serverClasses = {};
-// ---------------------------------------------------------------------------
+// ===========================================================================
function initClassScript() {
+ logToConsole(LOG_INFO, "[Asshat.Class]: Initializing class script ...");
+ serverClasses = initClassTable();
+ logToConsole(LOG_INFO, "[Asshat.Class]: Class script initialized successfully!");
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function initClassTable() {
let tempClasses = {
@@ -36,6 +39,14 @@ function initClassTable() {
this.connectCameraPosition = false;
this.connectCameraLookAt = false;
+
+ this.characterSelectCameraPosition = false;
+ this.characterSelectCameraLookAt = false;
+ this.characterSelectPedPosition = false;
+ this.characterSelectPedHeading = false;
+ this.characterSelectInterior = false;
+ this.characterSelectDimension = false;
+
this.hour = 0;
this.minute = 0
this.weather = 0
@@ -44,10 +55,13 @@ function initClassTable() {
this.useGUI = true;
this.guiColour = [200, 200, 200];
this.showLogo = true;
+ this.inflationMultiplier = 1;
this.antiCheat = {
enabled: false,
checkGameScripts: false,
+ gameScriptWhiteListEnabled: false,
+ gameScriptBlackListEnabled: false,
gameScriptWhiteList: [],
gameScriptBlackList: [],
};
@@ -55,6 +69,13 @@ function initClassTable() {
this.discordBotToken = "";
this.discordEnabled = false;
+ this.createJobPickups = false;
+ this.createBusinessPickups = false;
+ this.createHousePickups = false;
+ this.createJobBlips = false;
+ this.createBusinessBlips = false;
+ this.createHouseBlips = false;
+
if(dbAssoc) {
this.databaseId = dbAssoc["svr_id"];
this.name = dbAssoc["svr_name"];
@@ -69,8 +90,17 @@ function initClassTable() {
this.connectCameraPosition = toVector3(dbAssoc["svr_connectcam_pos_x"], dbAssoc["svr_connectcam_pos_y"], dbAssoc["svr_connectcam_pos_z"]);
this.connectCameraLookAt = toVector3(dbAssoc["svr_connectcam_lookat_x"], dbAssoc["svr_connectcam_lookat_y"], dbAssoc["svr_connectcam_lookat_z"]);
+
+ this.characterSelectCameraPosition = toVector3(dbAssoc["svr_charselect_cam_pos_x"], dbAssoc["svr_charselect_cam_pos_y"], dbAssoc["svr_charselect_cam_pos_z"]);
+ this.characterSelectCameraLookAt = toVector3(dbAssoc["svr_charselect_cam_lookat_x"], dbAssoc["svr_charselect_cam_lookat_y"], dbAssoc["svr_charselect_cam_lookat_z"]);
+ this.characterSelectPedPosition = toVector3(dbAssoc["svr_charselect_ped_pos_x"], dbAssoc["svr_charselect_ped_pos_y"], dbAssoc["svr_charselect_ped_pos_z"]);
+ this.characterSelectPedHeading = toFloat(dbAssoc["svr_charselect_ped_rot_z"]);
+ this.characterSelectInterior = toInteger(dbAssoc["svr_charselect_int"]);
+ this.characterSelectDimension = toInteger(dbAssoc["svr_charselect_int"]);
+
this.hour = toInteger(dbAssoc["svr_start_time_hour"]);
this.minute = toInteger(dbAssoc["svr_start_time_min"]);
+ this.minuteDuration = toInteger(dbAssoc["svr_time_min_duration"]);
this.weather = toInteger(dbAssoc["svr_start_weather"]);
this.fallingSnow = intToBool(dbAssoc["svr_start_snow_falling"]);
this.groundSnow = intToBool(dbAssoc["svr_start_snow_ground"]);
@@ -82,12 +112,23 @@ function initClassTable() {
this.antiCheat = {
enabled: intToBool(dbAssoc["svr_ac_enabled"]),
checkGameScripts: intToBool(dbAssoc["svr_ac_check_scripts"]),
+ gameScriptBlackListEnabled: intToBool(dbAssoc["svr_ac_script_bl"]),
+ gameScriptWhiteListEnabled: intToBool(dbAssoc["svr_ac_script_wl"]),
gameScriptWhiteList: [],
gameScriptBlackList: [],
};
- this.discordBotToken = "";
- this.discordEnabled = false;
+ this.discordBotToken = intToBool(dbAssoc["svr_discord_bot_token"]);
+ this.discordEnabled = intToBool(dbAssoc["svr_discord_bot_enabled"]);
+
+ this.createJobPickups = intToBool(dbAssoc["svr_job_pickups"]);
+ this.createBusinessPickups = intToBool(dbAssoc["svr_biz_pickups"]);
+ this.createHousePickups = intToBool(dbAssoc["svr_house_pickups"]);
+ this.createJobBlips = intToBool(dbAssoc["svr_job_blips"]);
+ this.createBusinessBlips = intToBool(dbAssoc["svr_biz_blips"]);
+ this.createHouseBlips = intToBool(dbAssoc["svr_house_blips"]);
+
+ this.introMusicURL = dbAssoc["svr_intro_music"];
}
}
},
@@ -103,13 +144,10 @@ function initClassTable() {
this.clientVersion = "0.0.0";
this.loginAttemptsRemaining = 3;
- this.busRoute = null;
- this.busRouteStop = null;
- this.busRouteIsland = null;
-
- this.garbageRoute = null;
- this.garbageRouteStop = null;
- this.garbageRouteIsland = null;
+ this.jobRoute = false;
+ this.jobRouteStop = false;
+ this.jobRouteIsland = false;
+ this.jobRouteVehicle = false;
this.spawned = false;
@@ -123,7 +161,6 @@ function initClassTable() {
this.switchingCharacter = false;
- this.tutorialState = AG_TUTORIAL_STATE_NONE;
this.tutorialStep = -1;
this.tutorialItem = null;
this.tutorialVehicle = null;
@@ -134,6 +171,7 @@ function initClassTable() {
this.jobLockerCache = new Array(9).fill(-1);
this.jobEquipmentCache = [];
+ this.jobUniform = 0;
this.itemActionState = AG_ITEM_ACTION_NONE;
this.itemActionItem = -1;
@@ -141,6 +179,33 @@ function initClassTable() {
this.alcoholLevel = 0;
this.pedState = AG_PEDSTATE_NONE;
+
+ this.promptType = AG_PROMPT_NONE;
+
+ this.businessOrderAmount = 0;
+ this.businessOrderBusiness = -1;
+ this.businessOrderItem = -1;
+ this.businessOrderValue = -1;
+
+ this.syncPosition = null;
+ this.syncHeading = null;
+
+ this.twoFactorAuthenticationState = AG_2FA_STATE_NONE;
+ this.twoFactorAuthenticationCode = 0;
+
+ this.payDayAmount = 0;
+ this.payDayTickStart = 0;
+
+ this.creatingCharacter = false;
+ this.creatingCharacterSkin = -1;
+
+ this.streamingRadioStation = -1;
+ this.streamingRadioVolume = 25;
+
+ this.returnToPosition = null;
+ this.returnToHeading = null;
+ this.returnToInterior = null;
+ this.returnToDimension = null;
}
},
accountData: class {
@@ -166,7 +231,11 @@ function initClassTable() {
this.keyBinds = [];
this.contacts = [];
this.subAccounts = [];
- this.loggedIn = false;
+
+ this.emailVerificationCode = "";
+ this.twoFactorAuthVerificationCode = "";
+
+ this.chatScrollLines = 1;
if(dbAssoc) {
this.databaseId = dbAssoc["acct_id"];
@@ -174,15 +243,16 @@ function initClassTable() {
this.password = dbAssoc["acct_pass"];
this.registerDate = dbAssoc["acct_when_made"];
this.flags = {
- moderation: dbAssoc["acct_mod_flags"],
- settings: dbAssoc["acct_settings"],
- admin: dbAssoc["acct_staff_flags"],
+ moderation: dbAssoc["acct_svr_mod_flags"],
+ settings: dbAssoc["acct_svr_settings"],
+ admin: dbAssoc["acct_svr_staff_flags"],
};
- this.staffTitle = dbAssoc["acct_staff_title"];
- this.ircAccount = dbAssoc["acct_irc"] || "None";
+ this.staffTitle = dbAssoc["acct_svr_staff_title"];
+ this.ircAccount = dbAssoc["acct_irc"];
this.discordAccount = dbAssoc["acct_discord"];
- this.settings = dbAssoc["acct_settings"];
+ this.settings = dbAssoc["acct_svr_settings"];
this.emailAddress = dbAssoc["acct_email"];
+ this.whenRegistered = dbAssoc["acct_when_registered"];
this.ipAddress = dbAssoc["ipstring"];
this.notes = [];
@@ -190,7 +260,10 @@ function initClassTable() {
this.keyBinds = [];
this.contacts = [];
this.subAccounts = [];
- this.loggedIn = false;
+
+ this.emailVerificationCode = dbAssoc["acct_code_verifyemail"];
+ this.twoFactorAuthVerificationCode = dbAssoc["acct_code_2fa"];
+ this.chatScrollLines = dbAssoc["acct_svr_chat_scroll_lines"];
}
}
},
@@ -268,11 +341,10 @@ function initClassTable() {
this.server = 0;
this.firstName = "John";
this.lastName = "Doe";
+ this.middleName = "Q";
this.account = 0;
this.skin = 0;
this.cash = 0;
- this.placeOfOrigin = "";
- this.dateOfBirth = "";
this.spawnPosition = toVector3(0.0, 0.0, 0.0);
this.spawnHeading = 0.0;
this.lastLogin = 0;
@@ -289,28 +361,79 @@ function initClassTable() {
this.interior = 0;
this.dimension = 0;
this.pedScale = toVector3(1.0, 1.0, 1.0);
+ this.walkStyle = 0;
+ this.fightStyle = 0;
+ this.health = 100;
+ this.armour = 100;
+ this.inHouse = 0;
+ this.inBusiness = 0;
+
+ this.bodyParts = {
+ hair: [0,0],
+ head: [0,0],
+ upper: [0,0],
+ lower: [0,0],
+ };
+
+ this.bodyProps = {
+ hair: [0,0],
+ eyes: [0,0],
+ head: [0,0],
+ leftHand: [0,0],
+ rightHand: [0,0],
+ leftWrist: [0,0],
+ rightWrist: [0,0],
+ hip: [0,0],
+ leftFoot: [0,0],
+ rightFoot: [0,0],
+ };
if(dbAssoc) {
this.databaseId = dbAssoc["sacct_id"];
- this.server = dbAssoc["sacct_server"];
+ this.server = toInteger(dbAssoc["sacct_server"]);
this.firstName = dbAssoc["sacct_name_first"];
this.lastName = dbAssoc["sacct_name_last"];
- this.account = dbAssoc["sacct_acct"];
- this.skin = dbAssoc["sacct_skin"];
- this.cash = dbAssoc["sacct_cash"];
- this.placeOfOrigin = dbAssoc["sacct_origin"];
- this.dateOfBirth = dbAssoc["sacct_when_born"];
- this.spawnPosition = toVector3(dbAssoc["sacct_pos_x"], dbAssoc["sacct_pos_y"], dbAssoc["sacct_pos_z"]);
+ this.middleName = dbAssoc["sacct_name_middle"] || "";
+ this.account = toInteger(dbAssoc["sacct_acct"]);
+ this.skin = toInteger(dbAssoc["sacct_svr_skin"]);
+ this.cash = toInteger(dbAssoc["sacct_cash"]);
+ this.spawnPosition = toVector3(toFloat(dbAssoc["sacct_pos_x"]), toFloat(dbAssoc["sacct_pos_y"]), toFloat(dbAssoc["sacct_pos_z"]));
this.spawnHeading = toFloat(dbAssoc["sacct_angle"]);
- this.lastLogin = toInteger(dbAssoc["sacct_last_login"]);
- this.clan = toInteger(dbAssoc["sacct_clan"]);
- this.clanFlags = toInteger(dbAssoc["sacct_clan_flags"]);
- this.clanRank = toInteger(dbAssoc["sacct_clan_rank"]);
- this.clanTitle = toInteger(dbAssoc["sacct_clan_title"]);
- this.job = dbAssoc["sacct_job"];
- this.interior = dbAssoc["sacct_int"];
- this.dimension = dbAssoc["sacct_vw"];
- this.pedScale = toVector3(dbAssoc["sacct_scale_x"], dbAssoc["sacct_scale_y"], dbAssoc["sacct_scale_z"]);
+ this.lastLogin = toInteger(dbAssoc["sacct_when_lastlogin"]);
+ this.clan = toInteger(dbAssoc["sacct_svr_clan"]);
+ this.clanFlags = toInteger(dbAssoc["sacct_svr_clan_flags"]);
+ this.clanRank = toInteger(dbAssoc["sacct_svr_clan_rank"]);
+ this.clanTitle = toInteger(dbAssoc["sacct_svr_clan_title"]);
+ this.job = toInteger(dbAssoc["sacct_svr_job"]);
+ this.interior = toInteger(dbAssoc["sacct_int"]);
+ this.dimension = toInteger(dbAssoc["sacct_vw"]);
+ this.pedScale = toVector3(toFloat(dbAssoc["sacct_svr_scale_x"]), toFloat(dbAssoc["sacct_svr_scale_y"]), toFloat(dbAssoc["sacct_svr_scale_z"]));
+ this.walkStyle = toInteger(dbAssoc["sacct_svr_walkstyle"]);
+ this.fightStyle = toInteger(dbAssoc["sacct_svr_fightstyle"]);
+ this.health = toInteger(dbAssoc["sacct_health"]);
+ this.armour = toInteger(dbAssoc["sacct_armour"]);
+ this.inHouse = toInteger(dbAssoc["sacct_inhouse"]);
+ this.inBusiness = toInteger(dbAssoc["sacct_inbusiness"]);
+
+ this.bodyParts = {
+ hair: [toInteger(dbAssoc["sacct_svr_hd_part_hair_model"]) || 0, toInteger(dbAssoc["sacct_svr_hd_part_hair_texture"]) || 0],
+ head: [toInteger(dbAssoc["sacct_svr_hd_part_head_model"]) || 0, toInteger(dbAssoc["sacct_svr_hd_part_head_texture"]) || 0],
+ upper: [toInteger(dbAssoc["sacct_svr_hd_part_upper_model"]) || 0, toInteger(dbAssoc["sacct_svr_hd_part_upper_texture"]) || 0],
+ lower: [toInteger(dbAssoc["sacct_svr_hd_part_lower_model"]) || 0, toInteger(dbAssoc["sacct_svr_hd_part_lower_texture"]) || 0],
+ };
+
+ this.bodyProps = {
+ hair: [toInteger(dbAssoc["sacct_svr_hd_prop_hair_model"]) || 0, toInteger(dbAssoc["sacct_svr_hd_prop_hair_texture"]) || 0],
+ eyes: [toInteger(dbAssoc["sacct_svr_hd_prop_eyes_model"]) || 0, toInteger(dbAssoc["sacct_svr_hd_prop_eyes_texture"]) || 0],
+ head: [toInteger(dbAssoc["sacct_svr_hd_prop_head_model"]) || 0, toInteger(dbAssoc["sacct_svr_hd_prop_head_texture"]) || 0],
+ leftHand: [toInteger(dbAssoc["sacct_svr_hd_prop_lefthand_model"]) || 0, toInteger(dbAssoc["sacct_svr_hd_prop_lefthand_texture"]) || 0],
+ rightHand: [toInteger(dbAssoc["sacct_svr_hd_prop_righthand_model"]) || 0, toInteger(dbAssoc["sacct_svr_hd_prop_righthand_texture"]) || 0],
+ leftWrist: [toInteger(dbAssoc["sacct_svr_hd_prop_leftwrist_model"]) || 0, toInteger(dbAssoc["sacct_svr_hd_prop_leftwrist_texture"]) || 0],
+ rightWrist: [toInteger(dbAssoc["sacct_svr_hd_prop_rightwrist_model"]) || 0, toInteger(dbAssoc["sacct_svr_hd_prop_rightwrist_texture"]) || 0],
+ hip: [toInteger(dbAssoc["sacct_svr_hd_prop_hip_model"]) || 0, toInteger(dbAssoc["sacct_svr_hd_prop_hip_texture"]) || 0],
+ leftFoot: [toInteger(dbAssoc["sacct_svr_hd_prop_leftfoot_model"]) || 0, toInteger(dbAssoc["sacct_svr_hd_prop_leftfoot_texture"]) || 0],
+ rightFoot: [toInteger(dbAssoc["sacct_svr_hd_prop_rightfoot_model"]) || 0, toInteger(dbAssoc["sacct_svr_hd_prop_rightfoot_texture"]) || 0],
+ };
}
}
},
@@ -325,7 +448,8 @@ function initClassTable() {
this.hasInterior = false;
this.index = -1;
this.needsSaved = false;
- this.itemCache = [];
+ this.floorItemCache = [];
+ this.storageItemCache = [];
this.entrancePosition = false;
this.entranceRotation = 0.0;
@@ -411,6 +535,8 @@ function initClassTable() {
this.ownerType = AG_HOUSEOWNER_NONE;
this.ownerId = 0;
this.buyPrice = 0;
+ this.rentPrice = 0;
+ this.renter = 0;
this.locked = false;
this.hasInterior = false;
this.index = -1;
@@ -441,6 +567,8 @@ function initClassTable() {
this.ownerType = toInteger(dbAssoc["house_owner_type"]);
this.ownerId = toInteger(dbAssoc["house_owner_id"]);
this.buyPrice = toInteger(dbAssoc["house_buy_price"]);
+ this.rentPrice = toInteger(dbAssoc["house_rent_price"]);
+ this.renter = toInteger(dbAssoc["house_renter"]);
this.locked = intToBool(toInteger(dbAssoc["house_locked"]));
this.hasInterior = intToBool(toInteger(dbAssoc["house_has_interior"]));
@@ -464,7 +592,7 @@ function initClassTable() {
constructor(dbAssoc) {
this.databaseId = 0;
this.name = "";
- this.owner = 0;
+ this.ownerId = 0;
this.tag = "";
this.enabled = false;
this.index = -1;
@@ -573,6 +701,22 @@ function initClassTable() {
this.colour3 = (vehicle) ? vehicle.colour3 : 1;
this.colour4 = (vehicle) ? vehicle.colour4 : 1;
+ this.extras = [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ ];
+
// Vehicle Attributes
this.locked = false;
this.engine = false;
@@ -595,7 +739,7 @@ function initClassTable() {
this.ownerType = toInteger(dbAssoc["veh_owner_type"]);
this.ownerId = toInteger(dbAssoc["veh_owner_id"]);
this.buyPrice = toInteger(dbAssoc["veh_buy_price"]);
- this.rentPrice = toInteger(dbAssoc["veh_buy_price"]);
+ this.rentPrice = toInteger(dbAssoc["veh_rent_price"]);
// Position and Rotation
this.spawnPosition = toVector3(dbAssoc["veh_pos_x"], dbAssoc["veh_pos_y"], dbAssoc["veh_pos_z"]);
@@ -616,6 +760,23 @@ function initClassTable() {
this.colour3 = toInteger(dbAssoc["veh_col3"]);
this.colour4 = toInteger(dbAssoc["veh_col4"]);
+ // Extras (components on SA, extras on IV+)
+ this.extras = [
+ toInteger(dbAssoc["veh_extra1"]),
+ toInteger(dbAssoc["veh_extra2"]),
+ toInteger(dbAssoc["veh_extra3"]),
+ toInteger(dbAssoc["veh_extra4"]),
+ toInteger(dbAssoc["veh_extra5"]),
+ toInteger(dbAssoc["veh_extra6"]),
+ toInteger(dbAssoc["veh_extra7"]),
+ toInteger(dbAssoc["veh_extra8"]),
+ toInteger(dbAssoc["veh_extra9"]),
+ toInteger(dbAssoc["veh_extra10"]),
+ toInteger(dbAssoc["veh_extra11"]),
+ toInteger(dbAssoc["veh_extra12"]),
+ toInteger(dbAssoc["veh_extra13"]),
+ ];
+
// Vehicle Attributes
this.locked = intToBool(toInteger(dbAssoc["veh_locked"]));
this.engine = intToBool(toInteger(dbAssoc["veh_engine"]));
@@ -629,7 +790,12 @@ function initClassTable() {
this.insuranceAccount = toInteger(0);
this.fuel = toInteger(0);
this.flags = toInteger(0);
+ this.needsSaved = false;
+ this.whoAdded = toInteger(dbAssoc["veh_who_added"]);
+ this.whenAdded = toInteger(dbAssoc["veh_when_added"]);
}
+
+ this.streamingRadioStation = -1;
}
},
commandData: class {
@@ -660,8 +826,8 @@ function initClassTable() {
this.crimeType = crimeType;
this.suspectId = suspectId;
this.reporterId = reporterId;
- this.whenCommitted = new Date().getTime();
- this.whenReported = new Date().getTime();
+ this.whenCommitted = 0;
+ this.whenReported = 0;
this.databaseId = 0;
}
},
@@ -694,8 +860,8 @@ function initClassTable() {
this.blipModel = dbAssoc["job_blip"];
this.pickupModel = dbAssoc["job_pickup"];
this.colour = toColour(dbAssoc["job_colour_r"], dbAssoc["job_colour_g"], dbAssoc["job_colour_b"], 255);
- this.whiteListEnabled = dbAssoc["job_whitelist"];
- this.blackListEnabled = dbAssoc["job_blacklist"];
+ this.whiteListEnabled = dbAssoc["job_wl"];
+ this.blackListEnabled = dbAssoc["job_bl"];
this.walkieTalkieFrequency = dbAssoc["job_walkietalkiefreq"];
this.equipment = [];
@@ -832,7 +998,7 @@ function initClassTable() {
}
},
keyBindData: class {
- constructor(dbAssoc = false, key = 0, commandString = "") {
+ constructor(dbAssoc = false, key = 0, commandString = "", keyState = AG_KEYSTATE_UP) {
this.databaseId = 0;
this.key = key;
this.account = 0;
@@ -895,12 +1061,34 @@ function initClassTable() {
this.range = range;
}
},
+ excludedGroundSnowModel: class {
+ constructor(model) {
+ this.model = model;
+ }
+ },
interiorTemplateData: class {
constructor(exitPosition, exitInterior) {
this.exitPosition = exitPosition;
this.exitInterior = exitInterior;
}
},
+ radioStationData: class {
+ constructor(dbAssoc) {
+ this.databaseId = 0;
+ this.name = "";
+ this.url = "";
+ this.genre = "";
+ this.codec = "";
+
+ if(dbAssoc) {
+ this.databaseId = dbAssoc["radio_id"];
+ this.name = dbAssoc["radio_name"];
+ this.url = dbAssoc["radio_url"];
+ this.genre = dbAssoc["radio_genre"];
+ this.codec = dbAssoc["radio_codec"];
+ }
+ }
+ },
itemData: class {
constructor(dbAssoc = false) {
this.databaseId = 0;
@@ -919,6 +1107,7 @@ function initClassTable() {
this.amount = 0;
this.value = 0;
this.enabled = false;
+ this.extra = false;
if(dbAssoc) {
this.databaseId = toInteger(dbAssoc["item_id"]);
@@ -946,6 +1135,7 @@ function initClassTable() {
this.useType = AG_ITEM_USETYPE_NONE;
this.useId = 0;
this.useValue = 0;
+ this.maxValue = 0;
this.dropType = AG_ITEM_DROPTYPE_NONE;
this.useId = 0;
this.dropPosition = toVector3(0.0, 0.0, 0.0);
@@ -953,6 +1143,10 @@ function initClassTable() {
this.dropScale = toVector3(0.0, 0.0, 0.0);
this.dropModel = 0;
this.orderPrice = 0;
+ this.orderValue = 0;
+ this.demandMultiplier = 1;
+ this.supplyMultiplier = 1;
+ this.riskMultiplier = 1;
this.needsSaved = false;
this.switchDelay = 0;
this.pickupDelay = 0;
@@ -974,10 +1168,12 @@ function initClassTable() {
this.dropModel = toInteger(dbAssoc["item_type_drop_model"]);
this.useId = toInteger(dbAssoc["item_type_use_id"]);
this.useValue = toInteger(dbAssoc["item_type_use_value"]);
+ this.maxValue = toInteger(dbAssoc["item_type_max_value"]);
this.orderPrice = toInteger(dbAssoc["item_type_order_price"]);
+ this.orderValue = toInteger(dbAssoc["item_type_order_value"]);
this.demandMultiplier = toFloat(dbAssoc["item_type_demand_multiplier"]);
this.supplyMultiplier = toFloat(dbAssoc["item_type_supply_multiplier"]);
- this.orderPrice = toInteger(dbAssoc["item_type_order_price"]);
+ this.riskMultiplier = toFloat(dbAssoc["item_type_risk_multiplier"]);
this.size = toInteger(dbAssoc["item_type_size"]);
this.capacity = toInteger(dbAssoc["item_type_capacity"]);
this.useDelay = toInteger(dbAssoc["item_type_delay_use"]);
@@ -989,22 +1185,166 @@ function initClassTable() {
this.dropDelay = toInteger(dbAssoc["item_type_delay_drop"]);
}
}
+ },
+ npcData: class {
+ constructor(dbAssoc) {
+ this.databaseId = 0;
+ this.server = 0;
+ this.firstName = "John";
+ this.lastName = "Doe";
+ this.middleName = "Q";
+ this.skin = 0;
+ this.cash = 0;
+ this.spawnPosition = toVector3(0.0, 0.0, 0.0);
+ this.spawnHeading = 0.0;
+ this.clan = 0;
+ this.isWorking = false;
+ this.jobUniform = this.skin;
+ this.lastJobVehicle = null;
+ this.job = 0;
+ this.weapons = [];
+ this.interior = 0;
+ this.dimension = 0;
+ this.pedScale = toVector3(1.0, 1.0, 1.0);
+ this.walkStyle = 0;
+ this.fightStyle = 0;
+ this.health = 100;
+ this.armour = 100;
+ this.currentAction = AG_NPCACTION_NONE;
+ this.triggers = [];
+
+ this.bodyParts = {
+ hair: [0,0],
+ head: [0,0],
+ upper: [0,0],
+ lower: [0,0],
+ };
+
+ this.bodyProps = {
+ hair: [0,0],
+ eyes: [0,0],
+ head: [0,0],
+ leftHand: [0,0],
+ rightHand: [0,0],
+ leftWrist: [0,0],
+ rightWrist: [0,0],
+ hip: [0,0],
+ leftFoot: [0,0],
+ rightFoot: [0,0],
+ };
+
+ if(dbAssoc) {
+ this.databaseId = toInteger(dbAssoc["npc_id"]);
+ this.server = toInteger(dbAssoc["npc_server"]);
+ this.firstName = dbAssoc["npc_name_first"];
+ this.lastName = dbAssoc["npc_name_last"];
+ this.middleName = dbAssoc["npc_name_middle"] || "";
+ this.skin = toInteger(dbAssoc["npc_skin"]);
+ this.cash = toInteger(dbAssoc["npc_cash"]);
+ this.spawnPosition = toVector3(toFloat(dbAssoc["npc_pos_x"]), toFloat(dbAssoc["npc_pos_y"]), toFloat(dbAssoc["npc_pos_z"]));
+ this.spawnHeading = toFloat(dbAssoc["npc_angle"]);
+ this.lastLogin = toInteger(dbAssoc["npc_when_lastlogin"]);
+ this.clan = toInteger(dbAssoc["npc_clan"]);
+ this.clanFlags = toInteger(dbAssoc["npc_clan_flags"]);
+ this.clanRank = toInteger(dbAssoc["npc_clan_rank"]);
+ this.clanTitle = toInteger(dbAssoc["npc_clan_title"]);
+ this.job = toInteger(dbAssoc["npc_job"]);
+ this.interior = toInteger(dbAssoc["npc_int"]);
+ this.dimension = toInteger(dbAssoc["npc_vw"]);
+ this.pedScale = toVector3(toFloat(dbAssoc["npc_scale_x"]), toFloat(dbAssoc["npc_scale_y"]), toFloat(dbAssoc["npc_scale_z"]));
+ this.walkStyle = toInteger(dbAssoc["npc_walkstyle"]);
+ this.fightStyle = toInteger(dbAssoc["npc_fightstyle"]);
+ this.health = toInteger(dbAssoc["npc_health"]);
+ this.armour = toInteger(dbAssoc["npc_armour"]);
+
+ this.bodyParts = {
+ hair: [toInteger(dbAssoc["npc_hd_part_hair_model"]) || 0, toInteger(dbAssoc["npc_hd_part_hair_texture"]) || 0],
+ head: [toInteger(dbAssoc["npc_hd_part_head_model"]) || 0, toInteger(dbAssoc["npc_hd_part_head_texture"]) || 0],
+ upper: [toInteger(dbAssoc["npc_hd_part_upper_model"]) || 0, toInteger(dbAssoc["npc_hd_part_upper_texture"]) || 0],
+ lower: [toInteger(dbAssoc["npc_hd_part_lower_model"]) || 0, toInteger(dbAssoc["npc_hd_part_lower_texture"]) || 0],
+ };
+
+ this.bodyProps = {
+ hair: [toInteger(dbAssoc["npc_hd_prop_hair_model"]) || 0, toInteger(dbAssoc["npc_hd_prop_hair_texture"]) || 0],
+ eyes: [toInteger(dbAssoc["npc_hd_prop_eyes_model"]) || 0, toInteger(dbAssoc["npc_hd_prop_eyes_texture"]) || 0],
+ head: [toInteger(dbAssoc["npc_hd_prop_head_model"]) || 0, toInteger(dbAssoc["npc_hd_prop_head_texture"]) || 0],
+ leftHand: [toInteger(dbAssoc["npc_hd_prop_lefthand_model"]) || 0, toInteger(dbAssoc["npc_hd_prop_lefthand_texture"]) || 0],
+ rightHand: [toInteger(dbAssoc["npc_hd_prop_righthand_model"]) || 0, toInteger(dbAssoc["npc_hd_prop_righthand_texture"]) || 0],
+ leftWrist: [toInteger(dbAssoc["npc_hd_prop_leftwrist_model"]) || 0, toInteger(dbAssoc["npc_hd_prop_leftwrist_texture"]) || 0],
+ rightWrist: [toInteger(dbAssoc["npc_hd_prop_rightwrist_model"]) || 0, toInteger(dbAssoc["npc_hd_prop_rightwrist_texture"]) || 0],
+ hip: [toInteger(dbAssoc["npc_hd_prop_hip_model"]) || 0, toInteger(dbAssoc["npc_hd_prop_hip_texture"]) || 0],
+ leftFoot: [toInteger(dbAssoc["npc_hd_prop_leftfoot_model"]) || 0, toInteger(dbAssoc["npc_hd_prop_leftfoot_texture"]) || 0],
+ rightFoot: [toInteger(dbAssoc["npc_hd_prop_rightfoot_model"]) || 0, toInteger(dbAssoc["npc_hd_prop_rightfoot_texture"]) || 0],
+ };
+ }
+ }
+ },
+ npcTriggerData: class {
+ constructor(dbAssoc) {
+ this.databaseId = 0;
+ this.npcId = 0;
+ this.index = 0;
+ this.npc = 0;
+ this.triggerType = 0;
+ this.conditions = [];
+ this.responses = [];
+
+ if(dbAssoc) {
+ this.databaseId = toInteger(dbAssoc["npc_trig_id"]);
+ this.npc = toInteger(dbAssoc["npc_trig_npc"]);
+ this.triggerType = toInteger(dbAssoc["npc_trig_type"]);
+ }
+ }
+ },
+ npcTriggerConditionData: class {
+ constructor(dbAssoc) {
+ this.databaseId = 0;
+ this.triggerId = 0;
+ this.index = 0;
+ this.conditionType = 0;
+ this.conditionValue = false;
+ this.matchType = false;
+
+ if(dbAssoc) {
+ this.databaseId = toInteger(dbAssoc["npc_trig_cond_id"]);
+ this.npc = toInteger(dbAssoc["npc_trig_cond_trig"]);
+ this.conditionType = toInteger(dbAssoc["npc_trig_cond_type"]);
+ this.conditionValue = toInteger(dbAssoc["npc_trig_cond_val"]);
+ this.matchType = toInteger(dbAssoc["npc_trig_cond_val"]);
+ }
+ }
+ },
+ npcTriggerResponseData: class {
+ constructor(dbAssoc) {
+ this.databaseId = 0;
+ this.triggerId = 0;
+ this.index = 0;
+ this.responseType = 0;
+ this.responseValue = false;
+
+ if(dbAssoc) {
+ this.databaseId = toInteger(dbAssoc["npc_trig_resp_id"]);
+ this.npc = toInteger(dbAssoc["npc_trig_resp_trig"]);
+ this.responseType = toInteger(dbAssoc["npc_trig_resp_type"]);
+ this.responseValue = toInteger(dbAssoc["npc_trig_resp_val"]);
+ }
+ }
}
}
return tempClasses;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function getClasses() {
return serverClasses;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function getClass(className) {
return serverClasses[className];
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
diff --git a/scripts/server/client.js b/scripts/server/client.js
index b7debb43..cf54b364 100644
--- a/scripts/server/client.js
+++ b/scripts/server/client.js
@@ -2,7 +2,7 @@
// Asshat-Gaming Roleplay
// https://github.com/VortrexFTW/gtac_asshat_rp
// Copyright (c) 2021 Asshat-Gaming (https://asshatgaming.com)
-// ---------------------------------------------------------------------------
+// ===========================================================================
// FILE: client.js
// DESC: Provides client communication and cross-endpoint operations
// TYPE: Server (JavaScript)
@@ -11,10 +11,10 @@
function initClientScript() {
logToConsole(LOG_DEBUG, "[Asshat.Client]: Initializing client script ...");
addAllNetworkHandlers();
- logToConsole(LOG_DEBUG, "[Asshat.Clan]: Initializing client script ...");
+ logToConsole(LOG_DEBUG, "[Asshat.Client]: Client script initialized!");
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function addAllNetworkHandlers() {
logToConsole(LOG_DEBUG, "[Asshat.Client]: Adding network handlers ...");
@@ -43,6 +43,7 @@ function addAllNetworkHandlers() {
addNetworkHandler("ag.clientReady", playerClientReady);
addNetworkHandler("ag.guiReady", playerGUIReady);
addNetworkHandler("ag.clientStarted", playerClientStarted);
+ addNetworkHandler("ag.clientStopped", playerClientStopped);
// Account
addNetworkHandler("ag.checkLogin", checkLogin);
@@ -62,30 +63,40 @@ function addAllNetworkHandlers() {
addNetworkHandler("ag.itemActionDelayComplete", playerItemActionDelayComplete);
addNetworkHandler("ag.weaponDamage", playerDamagedByPlayer);
+
+ addNetworkHandler("ag.player.position", updatePositionInPlayerData);
+ addNetworkHandler("ag.player.heading", updateHeadingInPlayerData);
+
+ addNetworkHandler("ag.skinSelected", playerFinishedSkinSelection);
+
+ addNetworkHandler("ag.clientInfo", updateConnectionLogOnClientInfoReceive);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function updatePlayerNameTag(client) {
+ //logToConsole(LOG_DEBUG, `[Asshat.Client] Sending ${getPlayerDisplayForConsole(client)}'s updated nametag to all players`);
triggerNetworkEvent("ag.nametag", null, client.name, getPlayerNameForNameTag(client), getPlayerColour(client), false, client.ping);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function updateAllPlayerNameTags() {
+ logToConsole(LOG_DEBUG, `[Asshat.Client] Sending updated nametags to all players`);
let clients = getClients();
for(let i in clients) {
updatePlayerNameTag(clients[i]);
}
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function updatePlayerPing(client) {
+ //logToConsole(LOG_DEBUG, `[Asshat.Client] Sending ${getPlayerDisplayForConsole(client)}'s ping to all players`);
triggerNetworkEvent("ag.ping", null, client.name, client.ping);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function playerClientReady(client) {
setEntityData(client, "ag.isReady", true, false);
@@ -95,14 +106,14 @@ function playerClientReady(client) {
}
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function playerGUIReady(client) {
setEntityData(client, "ag.guiReady", true, false);
logToConsole(LOG_DEBUG, `${getPlayerDisplayForConsole(client)}'s client GUI is initialized and ready!`);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function playerClientStarted(client) {
setEntityData(client, "ag.isStarted", true, false);
@@ -112,80 +123,93 @@ function playerClientStarted(client) {
}
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
+
+function playerClientStopped(client) {
+ logToConsole(LOG_DEBUG, `${getPlayerDisplayForConsole(client)}'s client resources have stopped (possibly error?). Kicking them from the server ...`);
+ client.disconnect();
+}
+
+// ===========================================================================
function showGameMessage(client, text, colour, duration) {
+ logToConsole(LOG_DEBUG, `[Asshat.Client] Showing game message to ${getPlayerDisplayForConsole(client)} (${text}) for ${duration} milliseconds`);
triggerNetworkEvent("ag.smallGameMessage", client, text, colour, duration);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function enableCityAmbienceForPlayer(client) {
+ logToConsole(LOG_DEBUG, `[Asshat.Client] Setting ${getPlayerDisplayForConsole(client)}'s city ambience to ${toUpperCase(getOnOffFromBool(false))}`);
triggerNetworkEvent("ag.ambience", client, true);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function disableCityAmbienceForPlayer(client) {
+ logToConsole(LOG_DEBUG, `[Asshat.Client] Setting ${getPlayerDisplayForConsole(client)}'s city ambience to ${toUpperCase(getOnOffFromBool(false))}`);
triggerNetworkEvent("ag.ambience", client, false);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function clearPlayerOwnedPeds(client) {
- logToConsole(LOG_DEBUG, `[Asshat.Utilities] Clearing peds owned by ${getPlayerDisplayForConsole(client)}`);
+ logToConsole(LOG_DEBUG, `[Asshat.Client] Clearing peds owned by ${getPlayerDisplayForConsole(client)}`);
triggerNetworkEvent("ag.clearPeds", client);
}
-// ---------------------------------------------------------------------------
-
-function updatePlayerJobType(client) {
- triggerNetworkEvent("ag.jobType", client, getJobIndexFromDatabaseId(getPlayerCurrentSubAccount(client).job));
-}
-
-// ---------------------------------------------------------------------------
+// ===========================================================================
function updatePlayerSpawnedState(client, state) {
+ logToConsole(LOG_DEBUG, `[Asshat.Client] Setting ${getPlayerDisplayForConsole(client)}'s spawned state ${toUpperCase(getOnOffFromBool(state))}`);
+ getPlayerData(client).spawned = true;
triggerNetworkEvent("ag.spawned", client, state);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function setPlayerControlState(client, state) {
- triggerNetworkEvent("ag.control", client, state);
+ logToConsole(LOG_DEBUG, `[Asshat.Client] Setting ${getPlayerDisplayForConsole(client)}'s control state ${toUpperCase(getOnOffFromBool(state))}`);
+ triggerNetworkEvent("ag.control", client, state, !state);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function updatePlayerShowLogoState(client, state) {
+ logToConsole(LOG_DEBUG, `[Asshat.Client] Setting ${getPlayerDisplayForConsole(client)}'s logo state ${toUpperCase(getOnOffFromBool(state))}`);
triggerNetworkEvent("ag.logo", client, state);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function restorePlayerCamera(client) {
+ logToConsole(LOG_DEBUG, `[Asshat.Client] Restoring ${getPlayerDisplayForConsole(client)}'s camera`);
triggerNetworkEvent("ag.restoreCamera", client);
}
-// -------------------------------------------------------------------------
+// ===========================================================================
function setPlayer2DRendering(client, hudState = false, labelState = false, smallGameMessageState = false, scoreboardState = false, hotBarState = false, itemActionDelayState = false) {
triggerNetworkEvent("ag.set2DRendering", client, hudState, labelState, smallGameMessageState, scoreboardState, hotBarState, itemActionDelayState);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function syncPlayerProperties(client) {
+ logToConsole(LOG_DEBUG, `[Asshat.Client] Sending signal to sync ${getPlayerDisplayForConsole(client)}'s player ped properties`);
triggerNetworkEvent("ag.player.sync", null, client.player);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function updatePlayerSnowState(client) {
- triggerNetworkEvent("ag.snow", client, getServerConfig().fallingSnow, getServerConfig().groundSnow);
+ if(doesGameHaveSnow(getServerGame())) {
+ logToConsole(LOG_DEBUG, `[Asshat.Client] Setting ${getPlayerDisplayForConsole(client)}'s snow state (Falling: ${toUpperCase(getOnOffFromBool(getServerConfig().fallingSnow))}, Ground: ${toUpperCase(getOnOffFromBool(getServerConfig().groundSnow))})`);
+ triggerNetworkEvent("ag.snow", client, getServerConfig().fallingSnow, getServerConfig().groundSnow);
+ }
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function sendExcludedModelsForGroundSnowToPlayer(client) {
if(getGameConfig().excludedGroundSnowModels[getServerGame()].length > 0) {
@@ -196,290 +220,672 @@ function sendExcludedModelsForGroundSnowToPlayer(client) {
}
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function sendRemovedWorldObjectsToPlayer(client) {
if(getGameConfig().removedWorldObjects[getServerGame()].length > 0) {
for(let i in getGameConfig().removedWorldObjects[getServerGame()]) {
- logToConsole(LOG_DEBUG, `[Asshat.Misc] Sending removed world object ${i} (${getGameConfig().removedWorldObjects[getServerGame()][i].model}) to ${client.name}`);
+ logToConsole(LOG_DEBUG, `[Asshat.Client] Sending removed world object ${i} (${getGameConfig().removedWorldObjects[getServerGame()][i].model}) to ${client.name}`);
triggerNetworkEvent("ag.removeWorldObject", client, getGameConfig().removedWorldObjects[getServerGame()][i].model, getGameConfig().removedWorldObjects[getServerGame()][i].position, getGameConfig().removedWorldObjects[getServerGame()][i].range);
}
}
return true;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function updatePlayerHotBar(client) {
+ logToConsole(LOG_DEBUG, `[Asshat.Client] Sending updated hotbar data to ${getPlayerDisplayForConsole(client)}`);
let tempHotBarItems = [];
for(let i in getPlayerData(client).hotBarItems) {
let itemImage = "";
let itemValue = 0;
let itemExists = false;
if(getPlayerData(client).hotBarItems[i] != -1) {
- let itemData = getItemData(getPlayerData(client).hotBarItems[i]);
- let itemTypeData = getItemTypeData(itemData.itemTypeIndex);
- itemExists = true;
- itemImage = itemTypeData.hotbarImage;
- itemValue = itemData.value;
+ if(getItemData(getPlayerData(client).hotBarItems[i])) {
+ let itemData = getItemData(getPlayerData(client).hotBarItems[i]);
+ let itemTypeData = getItemTypeData(itemData.itemTypeIndex);
+ itemExists = true;
+ itemImage = itemTypeData.hotbarImage;
+ itemValue = itemData.value;
+ }
}
tempHotBarItems.push([i, itemExists, itemImage, itemValue]);
}
triggerNetworkEvent("ag.hotbar", client, getPlayerData(client).activeHotBarSlot, tempHotBarItems);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function setPlayerWeaponDamageEnabled(client, state) {
+ logToConsole(LOG_DEBUG, `[Asshat.Client] Sending weapon damage state for ${getPlayerDisplayForConsole(client)} to all players`);
triggerNetworkEvent("ag.weaponDamageEnabled", null, client.name, state);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function setPlayerWeaponDamageEvent(client, eventType) {
+ logToConsole(LOG_DEBUG, `[Asshat.Client] Sending weapon damage event (${eventType}) for ${getPlayerDisplayForConsole(client)} to all players`);
triggerNetworkEvent("ag.weaponDamageEvent", null, client.name, eventType);
+ getPlayerData(client).weaponDamageEvent = eventType;
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function sendJobRouteStopToPlayer(client, position, colour) {
+ logToConsole(LOG_DEBUG, `[Asshat.Client] Sending job route stop data to ${getPlayerDisplayForConsole(client)}`);
triggerNetworkEvent("ag.showJobRouteStop", client, position, colour);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function showPlayerLoginSuccessGUI(client) {
+ logToConsole(LOG_DEBUG, `[Asshat.Client] Sending login success GUI signal to ${getPlayerDisplayForConsole(client)}`);
triggerNetworkEvent("ag.loginSuccess", client);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function showPlayerLoginFailedGUI(client, errorMessage) {
+ logToConsole(LOG_DEBUG, `[Asshat.Client] Sending login failed GUI signal to ${getPlayerDisplayForConsole(client)}`);
triggerNetworkEvent("ag.loginFailed", client, errorMessage);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function showPlayerRegistrationSuccessGUI(client) {
+ logToConsole(LOG_DEBUG, `[Asshat.Client] Sending registration success GUI signal to ${getPlayerDisplayForConsole(client)}`);
triggerNetworkEvent("ag.registrationSuccess", client);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function showPlayerRegistrationFailedGUI(client, errorMessage) {
+ logToConsole(LOG_DEBUG, `[Asshat.Client] Sending registration failed GUI signal to ${getPlayerDisplayForConsole(client)}`);
triggerNetworkEvent("ag.registrationFailed", client, errorMessage);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function sendPlayerGUIColours(client) {
+ logToConsole(LOG_DEBUG, `[Asshat.Client] Sending GUI colours to ${getPlayerDisplayForConsole(client)}`);
triggerNetworkEvent("ag.guiColour", client, getServerConfig().guiColour[0], getServerConfig().guiColour[1], getServerConfig().guiColour[2]);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function sendPlayerGUIInit(client) {
+ logToConsole(LOG_DEBUG, `[Asshat.Client] Sending GUI init signal to ${getPlayerDisplayForConsole(client)}`);
triggerNetworkEvent("ag.guiInit", client);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function showPlayerLoginGUI(client, errorMessage = "") {
+ logToConsole(LOG_DEBUG, `[Asshat.Client] Sending show login GUI signal to ${getPlayerDisplayForConsole(client)}`);
triggerNetworkEvent("ag.showLogin", client);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function showPlayerRegistrationGUI(client, errorMessage = "") {
+ logToConsole(LOG_DEBUG, `[Asshat.Client] Sending show registration GUI signal to ${getPlayerDisplayForConsole(client)}`);
triggerNetworkEvent("ag.showRegistration", client);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function showPlayerNewCharacterGUI(client) {
+ logToConsole(LOG_DEBUG, `[Asshat.Client] Sending show new character GUI signal to ${getPlayerDisplayForConsole(client)}`);
triggerNetworkEvent("ag.showNewCharacter", client);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
-function showPlayerCharacterSelectGUI(client, firstName, lastName, placeOfOrigin, dateOfBirth, skin) {
- triggerNetworkEvent("ag.showCharacterSelect", client, firstName, lastName, placeOfOrigin, dateOfBirth, skin);
+function showPlayerCharacterSelectGUI(client, firstName, lastName, cash, clan, lastPlayed, skin) {
+ logToConsole(LOG_DEBUG, `[Asshat.Client] Sending character select GUI signal to ${getPlayerDisplayForConsole(client)}`);
+ triggerNetworkEvent("ag.showCharacterSelect", client, firstName, lastName, cash, clan, lastPlayed, skin);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
-function updatePlayerCharacterSelectGUI(client, firstName, lastName, placeOfOrigin, dateOfBirth, skin) {
- triggerNetworkEvent("ag.showCharacterSelect", client, firstName, lastName, placeOfOrigin, dateOfBirth, skin);
+function updatePlayerCharacterSelectGUI(client, firstName, lastName, cash, clan, lastPlayed, skin) {
+ logToConsole(LOG_DEBUG, `[Asshat.Client] Sending update character select GUI signal to ${getPlayerDisplayForConsole(client)}`);
+ triggerNetworkEvent("ag.switchCharacterSelect", client, firstName, lastName, cash, clan, lastPlayed, skin);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function showPlayerCharacterSelectSuccessGUI(client) {
+ logToConsole(LOG_DEBUG, `[Asshat.Client] Sending character select success GUI signal to ${getPlayerDisplayForConsole(client)}`);
triggerNetworkEvent("ag.characterSelectSuccess", client);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
+
+function showPlayerCharacterSelectFailedGUI(client) {
+ logToConsole(LOG_DEBUG, `[Asshat.Client] Sending character select failed GUI signal to ${getPlayerDisplayForConsole(client)}`);
+ triggerNetworkEvent("ag.characterSelectFailed", client);
+}
+
+// ===========================================================================
function showPlayerPromptGUI(client, promptMessage, promptTitle) {
+ logToConsole(LOG_DEBUG, `[Asshat.Client] Sending show prompt GUI signal to ${getPlayerDisplayForConsole(client)} (Title: ${promptTitle}, Message: ${promptMessage})`);
triggerNetworkEvent("ag.showPrompt", client, promptMessage, promptTitle);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
+
+function showPlayerInfoGUI(client, infoMessage, infoTitle) {
+ logToConsole(LOG_DEBUG, `[Asshat.Client] Sending show info GUI signal to ${getPlayerDisplayForConsole(client)} (Title: ${infoTitle}, Message: ${infoMessage})`);
+ triggerNetworkEvent("ag.showInfo", client, infoMessage, infoTitle);
+}
+
+// ===========================================================================
+
+function showPlayerErrorGUI(client, errorMessage, errorTitle) {
+ logToConsole(LOG_DEBUG, `[Asshat.Client] Sending show error GUI signal to ${getPlayerDisplayForConsole(client)} (Title: ${errorTitle}, Message: ${errorMessage})`);
+ triggerNetworkEvent("ag.showInfo", client, errorMessage, errorTitle);
+}
+
+// ===========================================================================
function sendRunCodeToClient(client, code, returnTo) {
+ logToConsole(LOG_DEBUG, `[Asshat.Client] Sending runcode to ${getPlayerDisplayForConsole(client)} (returnTo: ${getPlayerDisplayForConsole(getClientFromIndex(returnTo))}, Code: ${code})`);
triggerNetworkEvent("ag.runCode", client, code, returnTo);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function sendPlayerWorkingState(client, state) {
+ logToConsole(LOG_DEBUG, `[Asshat.Client] Sending working state (${toUpperCase(getYesNoFromBool(state))}) to ${getPlayerDisplayForConsole(client)}`);
triggerNetworkEvent("ag.working", client, state);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function sendPlayerJobType(client, jobType) {
+ logToConsole(LOG_DEBUG, `[Asshat.Client] Sending job type (${jobType}) to ${getPlayerDisplayForConsole(client)}`);
triggerNetworkEvent("ag.jobType", client, jobType);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function sendPlayerStopJobRoute(client) {
+ logToConsole(LOG_DEBUG, `[Asshat.Client] Sending signal to abort job route to ${getPlayerDisplayForConsole(client)}`);
triggerNetworkEvent("ag.stopJobRoute", client);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function sendPlayerMouseCameraToggle(client) {
+ logToConsole(LOG_DEBUG, `[Asshat.Client] Sending signal to toggle mouse camera ${getPlayerDisplayForConsole(client)}`);
triggerNetworkEvent("ag.mouseCamera", client);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function sendPlayerMouseCursorToggle(client) {
+ logToConsole(LOG_DEBUG, `[Asshat.Client] Sending signal to toggle mouse cursor ${getPlayerDisplayForConsole(client)}`);
triggerNetworkEvent("ag.mouseCursor", client);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function sendAddAccountKeyBindToClient(client, key, keyState) {
+ logToConsole(LOG_DEBUG, `[Asshat.Client] Sending added keybind to ${getPlayerDisplayForConsole(client)} (Key: ${sdl.getKeyName(key)}, State: ${(keyState) ? "down" : "up"})`);
triggerNetworkEvent("ag.addKeyBind", client, toInteger(key), (keyState) ? KEYSTATE_DOWN : KEYSTATE_UP);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
-function sendRemoveAccountKeyBindToClient(client, key, keyState) {
+function sendRemoveAccountKeyBindToClient(client, key) {
+ logToConsole(LOG_DEBUG, `[Asshat.Client] Sending deleted keybind to ${getPlayerDisplayForConsole(client)} (Key: ${sdl.getKeyName(key)})`);
triggerNetworkEvent("ag.delKeyBind", client, toInteger(key));
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function sendPlayerSetPosition(client, position) {
+ logToConsole(LOG_DEBUG, `[Asshat.Client] Sending set position signal to ${getPlayerDisplayForConsole(client)} (Position: ${position.x}, ${position.y}, ${position.z})`);
triggerNetworkEvent("ag.position", client, position);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function sendPlayerSetHeading(client, heading) {
+ logToConsole(LOG_DEBUG, `[Asshat.Client] Sending set heading signal to ${getPlayerDisplayForConsole(client)} (Heading: ${heading})`);
triggerNetworkEvent("ag.heading", client, heading);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function sendPlayerSetInterior(client, interior) {
+ logToConsole(LOG_DEBUG, `[Asshat.Client] Sending set interior signal to ${getPlayerDisplayForConsole(client)} (Interior: ${interior})`);
triggerNetworkEvent("ag.interior", client, interior);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function sendPlayerFrozenState(client, state) {
+ logToConsole(LOG_DEBUG, `[Asshat.Client] Sending set frozen signal to ${getPlayerDisplayForConsole(client)} (State: ${toUpperCase(getYesNoFromBool(state))})`);
triggerNetworkEvent("ag.frozen", client, state);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function givePlayerWeapon(client, weaponId, ammo, active) {
+ logToConsole(LOG_DEBUG, `[Asshat.Client] Sending signal to ${getPlayerDisplayForConsole(client)} to give weapon (Weapon: ${weaponId}, Ammo: ${ammo})`);
triggerNetworkEvent("ag.giveWeapon", client, weaponId, ammo, active);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function clearPlayerWeapons(client) {
+ logToConsole(LOG_DEBUG, `[Asshat.Client] Sending signal to ${getPlayerDisplayForConsole(client)} to clear weapons`);
triggerNetworkEvent("ag.clearWeapons", client);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function showPlayerNewCharacterFailedGUI(client, errorMessage) {
+ logToConsole(LOG_DEBUG, `[Asshat.Client] Sending new character failed GUI signal to ${getPlayerDisplayForConsole(client)}`);
triggerNetworkEvent("ag.newCharacterFailed", client, errorMessage);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function sendPlayerRemoveFromVehicle(client) {
+ logToConsole(LOG_DEBUG, `[Asshat.Client] Sending remove from vehicle signal to ${getPlayerDisplayForConsole(client)}`);
triggerNetworkEvent("ag.removeFromVehicle", client);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function sendChatBoxMessageToPlayer(client, message, colour) {
triggerNetworkEvent("ag.m", client, message, colour)
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function showPlayerItemTakeDelay(client, itemId) {
- triggerNetworkEvent("ag.showItemActionDelay", client, getItemTypeData(getItemData(itemId).itemTypeIndex).takeDelay);
+ if(getItemData(itemId)) {
+ let delay = getItemTypeData(getItemData(itemId).itemTypeIndex).pickupDelay;
+ if(delay > 0) {
+ logToConsole(LOG_DEBUG, `[Asshat.Client] Showing item TAKE delay to ${getPlayerDisplayForConsole(client)} (${delay} milliseconds)`);
+ triggerNetworkEvent("ag.showItemActionDelay", client, delay);
+ } else {
+ logToConsole(LOG_DEBUG, `[Asshat.Client] Showing item TAKE delay to ${getPlayerDisplayForConsole(client)} (instant)`);
+ playerTakeItem(client, itemId);
+ }
+ }
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function showPlayerItemUseDelay(client, itemSlot) {
- triggerNetworkEvent("ag.showItemActionDelay", client, getItemTypeData(getItemData(getPlayerData(client).hotBarItems[itemSlot]).itemTypeIndex).useDelay);
+ if(getItemData(getPlayerData(client).hotBarItems[itemSlot])) {
+ let delay = getItemTypeData(getItemData(getPlayerData(client).hotBarItems[itemSlot]).itemTypeIndex).useDelay;
+ if(delay > 0) {
+ logToConsole(LOG_DEBUG, `[Asshat.Client] Showing item USE delay to ${getPlayerDisplayForConsole(client)} (${delay} milliseconds)`);
+ triggerNetworkEvent("ag.showItemActionDelay", client, delay);
+ } else {
+ logToConsole(LOG_DEBUG, `[Asshat.Client] Showing item USE delay to ${getPlayerDisplayForConsole(client)} (instant)`);
+ playerUseItem(client, itemSlot);
+ }
+ }
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function showPlayerItemDropDelay(client, itemSlot) {
- triggerNetworkEvent("ag.showItemActionDelay", client, getItemTypeData(getItemData(getPlayerData(client).hotBarItems[itemSlot]).itemTypeIndex).dropDelay);
+ if(getItemData(getPlayerData(client).hotBarItems[itemSlot])) {
+ let delay = getItemTypeData(getItemData(getPlayerData(client).hotBarItems[itemSlot]).itemTypeIndex).dropDelay;
+ if(delay > 0) {
+ logToConsole(LOG_DEBUG, `[Asshat.Client] Showing item DROP delay to ${getPlayerDisplayForConsole(client)} (${delay} milliseconds)`);
+ triggerNetworkEvent("ag.showItemActionDelay", client, delay);
+ } else {
+ logToConsole(LOG_DEBUG, `[Asshat.Client] Showing item DROP delay to ${getPlayerDisplayForConsole(client)} (instant)`);
+ playerDropItem(client, itemSlot);
+ }
+ }
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function showPlayerItemPickupDelay(client, itemId) {
- triggerNetworkEvent("ag.showItemActionDelay", client, getItemTypeData(getItemData(itemId).itemTypeIndex).pickupDelay);
+ if(getItemData(itemId)) {
+ let delay = getItemTypeData(getItemData(itemId).itemTypeIndex).pickupDelay;
+ if(delay > 0) {
+ logToConsole(LOG_DEBUG, `[Asshat.Client] Showing item PICKUP delay to ${getPlayerDisplayForConsole(client)} (${delay} milliseconds)`);
+ triggerNetworkEvent("ag.showItemActionDelay", client, delay);
+ } else {
+ logToConsole(LOG_DEBUG, `[Asshat.Client] Showing item PICKUP delay to ${getPlayerDisplayForConsole(client)} (instant)`);
+ playerPickupItem(client, itemId);
+ }
+ }
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function showPlayerItemPutDelay(client, itemSlot) {
- triggerNetworkEvent("ag.showItemActionDelay", client, getItemTypeData(getItemData(getPlayerData(client).hotBarItems[itemSlot]).itemTypeIndex).putDelay);
+ if(getItemData(getPlayerData(client).hotBarItems[itemSlot])) {
+ let delay = getItemTypeData(getItemData(getPlayerData(client).hotBarItems[itemSlot]).itemTypeIndex).putDelay;
+ if(delay > 0) {
+ logToConsole(LOG_DEBUG, `[Asshat.Client] Showing item PUT delay to ${getPlayerDisplayForConsole(client)} (${delay} milliseconds)`);
+ triggerNetworkEvent("ag.showItemActionDelay", client, delay);
+ } else {
+ logToConsole(LOG_DEBUG, `[Asshat.Client] Showing item PUT delay to ${getPlayerDisplayForConsole(client)} (instant)`);
+ playerPutItem(client, itemSlot);
+ }
+ }
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function showPlayerItemSwitchDelay(client, itemSlot) {
if(itemSlot != -1) {
if(getPlayerData(client).hotBarItems[itemSlot] != -1) {
+ logToConsole(LOG_DEBUG, `[Asshat.Client] Showing item switch delay to ${getPlayerDisplayForConsole(client)} (${getItemTypeData(getItemData(getPlayerData(client).hotBarItems[itemSlot]).itemTypeIndex).switchDelay} milliseconds)`);
triggerNetworkEvent("ag.showItemActionDelay", client, getItemTypeData(getItemData(getPlayerData(client).hotBarItems[itemSlot]).itemTypeIndex).switchDelay);
} else {
+ logToConsole(LOG_DEBUG, `[Asshat.Client] Showing item switch delay to ${getPlayerDisplayForConsole(client)} (instant)`);
playerSwitchItem(client, itemSlot);
}
} else {
+ logToConsole(LOG_DEBUG, `[Asshat.Client] Showing item switch delay to ${getPlayerDisplayForConsole(client)} (instant)`);
playerSwitchItem(client, itemSlot);
}
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function sendPlayerDrunkEffect(client, amount, duration) {
+ logToConsole(LOG_DEBUG, `[Asshat.Client] Setting drunk effect for ${getPlayerDisplayForConsole(client)} to ${amount} for ${duration} milliseconds`);
triggerNetworkEvent("ag.drunkEffect", client, amount, duration);
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function sendPlayerClearPedState(client) {
+ logToConsole(LOG_DEBUG, `[Asshat.Client] Clearing ped state for ${getPlayerDisplayForConsole(client)}`);
triggerNetworkEvent("ag.clearPedState", client);
}
-// ---------------------------------------------------------------------------
\ No newline at end of file
+// ===========================================================================
+
+function playerDamagedByPlayer(client, damagerEntityName, weaponId, pedPiece, healthLoss) {
+ let damagerEntity = getPlayerFromParams(damagerEntityName);
+
+ if(isNull(damagerEntity)) {
+ logToConsole(LOG_DEBUG, `[Asshat.Client] ${getPlayerDisplayForConsole(client)}'s damager entity from ID is null`);
+ return false;
+ }
+
+ logToConsole(LOG_DEBUG, `[Asshat.Client] ${getPlayerDisplayForConsole(client)} was damaged by ${damagerEntity}`);
+
+ if(isNull(damagerEntity)) {
+ logToConsole(LOG_DEBUG, `[Asshat.Client] ${getPlayerDisplayForConsole(client)}'s damager client is INVALID`);
+ return false;
+ }
+
+ if(!getPlayerData(damagerEntity) || !getPlayerData(client)) {
+ logToConsole(LOG_DEBUG, `[Asshat.Client] ${getPlayerDisplayForConsole(client)}'s damager's client data is INVALID`);
+ return false;
+ }
+
+ logToConsole(LOG_DEBUG, `[Asshat.Client] ${getPlayerDisplayForConsole(client)}'s damager is ${getPlayerDisplayForConsole(damagerEntity)}`);
+
+ switch(getPlayerData(damagerEntity).weaponDamageEvent) {
+ case AG_WEAPON_DAMAGE_EVENT_TAZER:
+ logToConsole(LOG_DEBUG, `[Asshat.Client] ${getPlayerDisplayForConsole(client)}'s damager ${getPlayerDisplayForConsole(damagerEntity)} is using a tazer`);
+ if(!isPlayerTazed(client) && !isPlayerHandCuffed(client) && !isPlayerInAnyVehicle(client)) {
+ logToConsole(LOG_DEBUG, `[Asshat.Client] ${getPlayerDisplayForConsole(client)} was not previously tazed, binded, or in a vehicle. Taze successful`);
+ meActionToNearbyPlayers(damagerEntity, `electrifies ${getCharacterFullName(client)} with their tazer`);
+ tazePlayer(client);
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+// ===========================================================================
+
+function setPlayerCameraLookAt(client, cameraPosition, lookAtPosition) {
+ triggerNetworkEvent("ag.cameraLookAt", client, cameraPosition, lookAtPosition);
+}
+
+// ===========================================================================
+
+function setTimeMinuteDuration(client, minuteDuration) {
+ triggerNetworkEvent("ag.minuteDuration", client, minuteDuration);
+}
+
+// ===========================================================================
+
+function updatePositionInPlayerData(client, position) {
+ getPlayerData(client).syncPosition = position;
+}
+
+// ===========================================================================
+
+function updateHeadingInPlayerData(client, heading) {
+ getPlayerData(client).syncHeading = heading;
+}
+
+// ===========================================================================
+
+function forcePlayerIntoSkinSelect(client) {
+ if(getGameConfig().skinChangePosition[getServerGame()].length != 0) {
+ getPlayerData(client).returnToPosition = getPlayerPosition(client);
+ getPlayerData(client).returnToHeading = getPlayerHeading(client);
+ getPlayerData(client).returnToInterior = getPlayerInterior(client);
+ getPlayerData(client).returnToDimension = getPlayerDimension(client);
+
+ setPlayerPosition(client, getGameConfig().skinChangePosition[getServerGame()][0]);
+ setPlayerHeading(client, getGameConfig().skinChangePosition[getServerGame()][1]);
+ setPlayerInterior(client, getGameConfig().skinChangePosition[getServerGame()][2]);
+ setPlayerDimension(client, client.index+100);
+ }
+
+ triggerNetworkEvent("ag.skinSelect", client, true);
+}
+
+// ===========================================================================
+
+function playerSkinItemSelectComplete(client, skinId) {
+ getPlayerCurrentSubAccount(client).skin = skinId;
+}
+
+// ===========================================================================
+
+function updatePlayerCash(client) {
+ triggerNetworkEvent("ag.money", client, getPlayerCurrentSubAccount(client).cash);
+}
+
+// ===========================================================================
+
+function sendAllPoliceStationBlips(client) {
+ if(getGameConfig().blipSprites[getServerGame()].policeStation != -1) {
+ let tempBlips = [];
+ for(let i in getServerData().policeStations[getServerGame()]) {
+ tempBlips.push([
+ getGameConfig().blipSprites[getServerGame()].policeStation,
+ getServerData().policeStations[getServerGame()][i].position.x,
+ getServerData().policeStations[getServerGame()][i].position.y,
+ getServerData().policeStations[getServerGame()][i].position.z,
+ 3,
+ getColourByName("policeBlue"),
+ ]);
+ }
+ triggerNetworkEvent("ag.blips", client, tempBlips);
+ }
+}
+
+// ===========================================================================
+
+function sendAllFireStationBlips(client) {
+ if(getGameConfig().blipSprites[getServerGame()].fireStation != -1) {
+ let tempBlips = [];
+ for(let i in getServerData().fireStations[getServerGame()]) {
+ tempBlips.push([
+ getGameConfig().blipSprites[getServerGame()].fireStation,
+ getServerData().fireStations[getServerGame()][i].position.x,
+ getServerData().fireStations[getServerGame()][i].position.y,
+ getServerData().fireStations[getServerGame()][i].position.z,
+ 3,
+ getColourByName("firefighterRed"),
+ ]);
+ }
+ triggerNetworkEvent("ag.blips", client, tempBlips);
+ }
+}
+
+// ===========================================================================
+
+function sendAllHospitalBlips(client) {
+ if(getGameConfig().blipSprites[getServerGame()].hospital != -1) {
+ let tempBlips = [];
+ for(let i in getServerData().hospitals[getServerGame()]) {
+ tempBlips.push([
+ getGameConfig().blipSprites[getServerGame()].hospital,
+ getServerData().hospitals[getServerGame()][i].position.x,
+ getServerData().hospitals[getServerGame()][i].position.y,
+ getServerData().hospitals[getServerGame()][i].position.z,
+ 3,
+ getColourByName("medicPink"),
+ ]);
+ }
+ triggerNetworkEvent("ag.blips", client, tempBlips);
+ }
+}
+
+// ===========================================================================
+
+function sendAllAmmunationBlips(client) {
+ if(getGameConfig().blipSprites[getServerGame()].ammunation != -1) {
+ let tempBlips = [];
+ for(let i in getServerData().ammunations[getServerGame()]) {
+ tempBlips.push([
+ getGameConfig().blipSprites[getServerGame()].ammunation,
+ getServerData().ammunations[getServerGame()][i].position.x,
+ getServerData().ammunations[getServerGame()][i].position.y,
+ getServerData().ammunations[getServerGame()][i].position.z,
+ 3,
+ 0
+ ]);
+ }
+ triggerNetworkEvent("ag.blips", client, tempBlips);
+ }
+}
+
+// ===========================================================================
+
+function sendAllPayAndSprayBlips(client) {
+ if(getGameConfig().blipSprites[getServerGame()].payAndSpray != -1) {
+ let tempBlips = [];
+ for(let i in getServerData().payAndSprays[getServerGame()]) {
+ tempBlips.push([
+ getGameConfig().blipSprites[getServerGame()].payAndSpray,
+ getServerData().payAndSprays[getServerGame()][i].position.x,
+ getServerData().payAndSprays[getServerGame()][i].position.y,
+ getServerData().payAndSprays[getServerGame()][i].position.z,
+ 3,
+ 0
+ ]);
+ }
+ triggerNetworkEvent("ag.blips", client, tempBlips);
+ }
+}
+
+// ===========================================================================
+
+function sendAllFuelStationBlips(client) {
+ if(getGameConfig().blipSprites[getServerGame()].fuelStation != -1) {
+ let tempBlips = [];
+ for(let i in getServerData().fuelStations[getServerGame()]) {
+ tempBlips.push([
+ getGameConfig().blipSprites[getServerGame()].fuelStation,
+ getServerData().fuelStations[getServerGame()][i].position.x,
+ getServerData().fuelStations[getServerGame()][i].position.y,
+ getServerData().fuelStations[getServerGame()][i].position.z,
+ 3,
+ getColourByName("burntOrange"),
+ ]);
+ }
+ triggerNetworkEvent("ag.blips", client, tempBlips);
+ }
+}
+
+// ===========================================================================
+
+function sendPlayerSetHealth(client, health) {
+ triggerNetworkEvent("ag.health", client, health);
+}
+
+
+// ===========================================================================
+
+function sendPlayerSetArmour(client, armour) {
+ triggerNetworkEvent("ag.armour", client, armour);
+}
+
+// ===========================================================================
+
+function playerFinishedSkinSelection(client, allowedSkinIndex) {
+ if(allowedSkinIndex == -1) {
+ return false;
+ } else {
+ getPlayerCurrentSubAccount(client).skin = allowedSkins[getServerGame()][allowedSkinIndex][0];
+ if(isPlayerWorking(client)) {
+ messagePlayerAlert(client, "Your new skin has been saved but won't be shown until you stop working.");
+ setPlayerSkin(client, getJobData(getPlayerCurrentSubAccount(client).job).uniforms[getPlayerData(client).jobUniform].skinId);
+ }
+ deleteItem(getPlayerData(client).itemActionItem);
+ restorePlayerCamera(client);
+ cachePlayerHotBarItems(client);
+
+ setPlayerSkin(client, allowedSkins[getServerGame()][allowedSkinIndex][0]);
+ setPlayerPosition(client, getPlayerData(client).returnToPosition);
+ setPlayerHeading(client, getPlayerData(client).returnToHeading);
+ setPlayerInterior(client, getPlayerData(client).returnToInterior);
+ setPlayerDimension(client, getPlayerData(client).returnToDimension);
+
+ getPlayerData(client).returnToPosition = null;
+ getPlayerData(client).returnToHeading = null;
+ getPlayerData(client).returnToInterior = null;
+ getPlayerData(client).returnToDimension = null;
+
+ meActionToNearbyPlayers(client, `changes their skin to ${allowedSkins[getServerGame()][allowedSkinIndex][1]}`);
+ }
+ triggerNetworkEvent("ag.skinSelect", client, false);
+}
+
+// ===========================================================================
+
+function sendPlayerChatScrollLines(client, amount) {
+ triggerNetworkEvent("ag.chatScrollLines", client, amount);
+}
+
+// ===========================================================================
+
+function playRadioStreamForPlayer(client, streamURL) {
+ triggerNetworkEvent("ag.radioStream", client, streamURL);
+}
+
+// ===========================================================================
+
+function setPlayerStreamingRadioVolume(client, volumeLevel) {
+ triggerNetworkEvent("ag.radioVolume", client, volumeLevel);
+}
+
+// ===========================================================================
+
+function setVehicleLightsState(vehicle, state) {
+ triggerNetworkEvent("ag.veh.lights", null, vehicle.id, state);
+}
+
+// ===========================================================================
\ No newline at end of file
diff --git a/scripts/server/colour.js b/scripts/server/colour.js
index 97e7c64b..5084f5de 100644
--- a/scripts/server/colour.js
+++ b/scripts/server/colour.js
@@ -2,7 +2,7 @@
// Asshat-Gaming Roleplay
// https://github.com/VortrexFTW/gtac_asshat_rp
// Copyright (c) 2021 Asshat-Gaming (https://asshatgaming.com)
-// ---------------------------------------------------------------------------
+// ===========================================================================
// FILE: colour.js
// DESC: Provides colours, functions and usage
// TYPE: Server (JavaScript)
@@ -30,17 +30,18 @@ let serverColours = {
royalBlue: toColour(0, 0, 255, 255),
teal: toColour(0, 255, 255, 255),
orange: toColour(255, 128, 0, 255),
- softRed: toColour(205, 92, 92, 255),
+ softRed: toColour(205, 60, 60, 255),
softGreen: toColour(50, 205, 50, 255),
lightPurple: toColour(150, 0, 150, 255),
lightGrey: toColour(200, 200, 200, 255),
mediumGrey: toColour(150, 150, 150, 255),
darkGrey: toColour(64, 64, 64, 255),
- policeBlue: toColour(70, 130, 180, 255),
+ policeBlue: toColour(50, 80, 200, 255),
medicPink: toColour(219, 112, 147, 255),
- firefighterRed: toColour(205, 92, 92, 255),
- busDriverGreen: toColour(50, 205, 50, 255),
- taxiDriverYellow: toColour(240, 230, 140, 255),
+ firefighterRed: toColour(205, 60, 60, 255),
+ busDriverGreen: toColour(50, 160, 50, 255),
+ taxiDriverYellow: toColour(240, 230, 100, 255),
+ deliveryPurple: toColour(177, 156, 217, 255),
civilianWhite: toColour(200, 200, 200, 255),
burntYellow: toColour(210, 210, 0, 255),
burntOrange: toColour(210, 120, 0, 255),
@@ -49,28 +50,28 @@ let serverColours = {
businessBlue: toColour(0, 153, 255, 255),
houseGreen: toColour(17, 204, 17, 255),
clanOrange: toColour(255, 153, 0, 255),
- }
+ },
};
-// -------------------------------------------------------------------------
+// ===========================================================================
function getServerColours() {
return serverColours;
}
-// -------------------------------------------------------------------------
+// ===========================================================================
function getColourByType(typeName) {
return getServerColours().byType[typeName];
}
-// -------------------------------------------------------------------------
+// ===========================================================================
function getColourByName(colourName) {
return getServerColours().byName[colourName];
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function getPlayerColour(client) {
if(getPlayerData(client) != false) {
@@ -86,10 +87,49 @@ function getPlayerColour(client) {
return getColourByName("civilianWhite");
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function getBoolRedGreenInlineColour(boolVal) {
- return (!boolVal) ? "[#AA2222]" : "[#22AA22]";
+ return (!boolVal) ? "[#cd3c3c]" : "[#32cd32]";
}
-// ---------------------------------------------------------------------------
\ No newline at end of file
+// ===========================================================================
+
+function hexToRgb(h) {
+ return [
+ '0x'+h[1]+h[2]|0,
+ '0x'+h[3]+h[4]|0,
+ '0x'+h[5]+h[6]|0
+ ];
+}
+
+// ===========================================================================
+
+function rgbToHex(r, g, b) {
+ return "#"+((1<<24)+(r<<16)+(g<<8)+ b).toString(16).slice(1);
+}
+
+// ===========================================================================
+
+function getClientChatColour(client) {
+ let tempJob = getPlayerCurrentSubAccount(client).job;
+ if(tempJob != -1) {
+ if(getPlayerData(client).isWorking) {
+ return getJobData(tempJob).jobColour;
+ }
+ }
+ return getColourByName("white");
+}
+
+// ===========================================================================
+
+function getRandomRGB() {
+ return toColour.apply(null, [
+ getRandom(0, 255),
+ getRandom(0, 255),
+ getRandom(0, 255),
+ 255
+ ]);
+}
+
+// ===========================================================================
\ No newline at end of file
diff --git a/scripts/server/command.js b/scripts/server/command.js
index 95bcf1cd..6ddd57c3 100644
--- a/scripts/server/command.js
+++ b/scripts/server/command.js
@@ -2,7 +2,7 @@
// Asshat-Gaming Roleplay
// https://github.com/VortrexFTW/gtac_asshat_rp
// Copyright (c) 2021 Asshat-Gaming (https://asshatgaming.com)
-// ---------------------------------------------------------------------------
+// ===========================================================================
// FILE: command.js
// DESC: Provides command data, functions and usage
// TYPE: Server (JavaScript)
@@ -10,6 +10,8 @@
let serverCommands = [];
+// ===========================================================================
+
let builtInCommands = [
"refresh",
"restart",
@@ -23,16 +25,16 @@ let builtInCommands = [
"dumpdoc",
];
-// ---------------------------------------------------------------------------
+// ===========================================================================
function initCommandScript() {
- logToConsole(LOG_DEBUG, "[Asshat.Command]: Initializing commands script ...");
+ logToConsole(LOG_INFO, "[Asshat.Command]: Initializing commands script ...");
serverCommands = loadCommands();
- addAllCommandHandlers();
- logToConsole(LOG_DEBUG, "[Asshat.Command]: Initialized commands script!");
+ //addAllCommandHandlers();
+ logToConsole(LOG_INFO, "[Asshat.Command]: Initialized commands script!");
}
-// ---------------------------------------------------------------------------
+// ===========================================================================
function loadCommands() {
return {
@@ -44,10 +46,21 @@ function loadCommands() {
commandData("autolastchar", autoSelectLastCharacterCommand, "", getStaffFlagValue("none"), true, false, "Toggle whether to automatically spawn with the last character you played as"),
commandData("gui", toggleAccountGUICommand, "", getStaffFlagValue("none"), false, false, "Toggle whether to use GUI. If GUI is disabled on the server, it won't show even if you have GUI enabled."),
commandData("2fa", toggleAccountTwoFactorAuthCommand, "", getStaffFlagValue("none"), true, false, "Set up and use two-factor authentication."),
- commandData("setemail", setAccountEmailCommand, "", getStaffFlagValue("none"), true, false, "Sets your email. To reset your password, you must have a valid email set to your account."),
+ commandData("setemail", setAccountEmailCommand, "", getStaffFlagValue("none"), true, false, "Sets your email. To reset your password, you must have a valid email set and verified."),
+ commandData("verifyemail", verifyAccountEmailCommand, "", getStaffFlagValue("none"), true, false, "Confirms/verifies your email."),
commandData("setdiscord", setAccountDiscordCommand, "", getStaffFlagValue("none"), true, false, "Set up the integration for discord. Allows you to see info and use in-game commands on discord."),
],
ammunation: [],
+ antiCheat: [
+ //commandData("addacscriptwl", addAntiCheatWhiteListedScriptCommand, "