mirror of
https://github.com/iDisaster/GTAConnected.git
synced 2026-03-08 09:25:23 +00:00
Merge pull request #1 from iDisaster/claude/enhance-gta-server-9Dezg
Add comprehensive GTA IV freeroam server with multiple resources
This commit is contained in:
238
README.md
238
README.md
@@ -1 +1,237 @@
|
||||
# GTAConnected
|
||||
# GTAConnected - Liberty City Freeroam Server
|
||||
|
||||
A comprehensive GTA IV freeroam server for GTAConnected with multiple features including vehicle spawning, teleportation, admin tools, weather control, and enhanced chat.
|
||||
|
||||
## Features
|
||||
|
||||
- **Freeroam System** - Random spawning across Liberty City with starter weapons
|
||||
- **Vehicle Spawning** - 100+ GTA IV vehicles available via commands
|
||||
- **Teleportation** - 30+ preset locations across all Liberty City boroughs
|
||||
- **Admin System** - Full moderation tools (kick, ban, mute, freeze, etc.)
|
||||
- **World Control** - Weather and time manipulation
|
||||
- **Enhanced Chat** - Private messages, local chat, actions, and OOC chat
|
||||
- **Kill Tracking** - Statistics for kills, deaths, and K/D ratio
|
||||
|
||||
## Installation
|
||||
|
||||
1. Download and install GTAConnected server from [gtaconnected.com](https://gtaconnected.com)
|
||||
2. Copy all files from this repository to your GTAConnected server directory
|
||||
3. Start the server using `Server.exe` (Windows) or `./Server` (Linux)
|
||||
|
||||
## Server Structure
|
||||
|
||||
```
|
||||
GTAConnected/
|
||||
├── server.xml # Main server configuration
|
||||
├── README.md
|
||||
└── resources/
|
||||
├── freeroam/ # Player spawning and basic commands
|
||||
│ ├── meta.xml
|
||||
│ ├── server.js
|
||||
│ └── client.js
|
||||
├── vehicles/ # Vehicle spawning system
|
||||
│ ├── meta.xml
|
||||
│ └── server.js
|
||||
├── admin/ # Admin moderation tools
|
||||
│ ├── meta.xml
|
||||
│ └── server.js
|
||||
├── world/ # Weather and time control
|
||||
│ ├── meta.xml
|
||||
│ └── server.js
|
||||
├── chat/ # Enhanced chat system
|
||||
│ ├── meta.xml
|
||||
│ └── server.js
|
||||
└── teleport/ # Teleportation system
|
||||
├── meta.xml
|
||||
└── server.js
|
||||
```
|
||||
|
||||
## Commands
|
||||
|
||||
### Player Commands
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `/help` | Show all available commands |
|
||||
| `/spawn` | Respawn at a random location |
|
||||
| `/kill` | Kill yourself |
|
||||
| `/pos` | Show your current coordinates |
|
||||
| `/stats` | Show your kill/death statistics |
|
||||
| `/players` | List online players |
|
||||
| `/heal` | Restore your health |
|
||||
| `/armour` | Give yourself armour |
|
||||
| `/weapons` | Get all weapons |
|
||||
| `/skin <id>` | Change your player skin |
|
||||
|
||||
### Vehicle Commands
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `/v <name>` | Spawn a vehicle |
|
||||
| `/dv` | Delete your spawned vehicles |
|
||||
| `/vlist` | Show vehicle categories |
|
||||
| `/vsearch <name>` | Search for vehicles |
|
||||
| `/vcolor <c1> <c2>` | Change vehicle colors |
|
||||
| `/flip` | Flip your vehicle upright |
|
||||
| `/fix` | Repair your vehicle |
|
||||
| `/eject` | Exit current vehicle |
|
||||
|
||||
### Teleport Commands
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `/tp <location>` | Teleport to a location |
|
||||
| `/tplist` | Show all teleport locations |
|
||||
| `/tpsearch <name>` | Search for locations |
|
||||
| `/setpos <x> <y> <z>` | Teleport to coordinates |
|
||||
| `/savewaypoint <name>` | Save current position |
|
||||
| `/tpwp <name>` | Teleport to saved waypoint |
|
||||
| `/waypoints` | List your saved waypoints |
|
||||
| `/airport` | Quick teleport to airport |
|
||||
| `/hospital` | Quick teleport to hospital |
|
||||
|
||||
### World Commands
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `/weather <0-9>` | Set weather type |
|
||||
| `/time <hour>` | Set time of day |
|
||||
| `/morning` | Set time to 8:00 |
|
||||
| `/noon` | Set time to 12:00 |
|
||||
| `/evening` | Set time to 18:00 |
|
||||
| `/night` | Set time to 0:00 |
|
||||
| `/sunny` | Set sunny weather |
|
||||
| `/rain` | Set rainy weather |
|
||||
| `/thunder` | Set thunderstorm |
|
||||
| `/foggy` | Set foggy weather |
|
||||
| `/freezetime` | Toggle time freeze |
|
||||
| `/gettime` | Show current time |
|
||||
| `/getweather` | Show current weather |
|
||||
|
||||
### Chat Commands
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `/pm <player> <msg>` | Send private message |
|
||||
| `/r <message>` | Reply to last PM |
|
||||
| `/me <action>` | Roleplay action |
|
||||
| `/do <description>` | Roleplay description |
|
||||
| `/shout <message>` | Shout message |
|
||||
| `/ooc <message>` | Out-of-character chat |
|
||||
| `/local <message>` | Local area chat |
|
||||
|
||||
### Admin Commands
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `/ahelp` | Show admin commands |
|
||||
| `/kick <player> [reason]` | Kick a player |
|
||||
| `/ban <player> [reason]` | Ban a player |
|
||||
| `/unban <player>` | Unban a player |
|
||||
| `/mute <player>` | Mute a player |
|
||||
| `/unmute <player>` | Unmute a player |
|
||||
| `/freeze <player>` | Freeze a player |
|
||||
| `/unfreeze <player>` | Unfreeze a player |
|
||||
| `/slap <player>` | Slap a player |
|
||||
| `/goto <player>` | Teleport to player |
|
||||
| `/bring <player>` | Bring player to you |
|
||||
| `/announce <msg>` | Server announcement |
|
||||
| `/setadmin <player>` | Grant admin rights |
|
||||
| `/getip <player>` | Get player's IP |
|
||||
| `/sethealth <player> <hp>` | Set player health |
|
||||
| `/setarmour <player> <armor>` | Set player armour |
|
||||
| `/explode <player>` | Explode a player |
|
||||
| `/admins` | Show online admins |
|
||||
| `/report <message>` | Report to admins |
|
||||
|
||||
## Available Vehicles
|
||||
|
||||
### Sports & Super Cars
|
||||
- infernus, turismo, comet, banshee, sultan, coquette, feltzer
|
||||
- entityxf, adder, vacca, bullet, cheetah
|
||||
|
||||
### Muscle Cars
|
||||
- sabregt, stalion, vigero, dukes, ruiner, phoenix, gauntlet, dominator
|
||||
|
||||
### SUVs & Sedans
|
||||
- patriot, cavalcade, granger, huntley, landstalker
|
||||
- oracle, schafter, admiral, vincent, presidente, cognoscenti
|
||||
|
||||
### Emergency Vehicles
|
||||
- police, police2, fbi, fbi2, noose, ambulance, firetruk
|
||||
|
||||
### Motorcycles
|
||||
- nrg900, pcj600, sanchez, faggio, bati, akuma, hakuchou
|
||||
|
||||
### Aircraft & Boats
|
||||
- annihilator, maverick, polmav, buzzard, shamal
|
||||
- jetmax, marquis, predator, tropic, dinghy
|
||||
|
||||
## Teleport Locations
|
||||
|
||||
### Algonquin (Manhattan)
|
||||
- starjunction, middlepark, rotterdam, chinatown, exchange, happiness
|
||||
|
||||
### Broker/Dukes (Brooklyn/Queens)
|
||||
- broker, firefly, outlook, beach, hove, meadows, willis, airport
|
||||
|
||||
### Bohan (Bronx)
|
||||
- bohan, northholland, industrial
|
||||
|
||||
### Alderney (New Jersey)
|
||||
- alderney, alderneyport, westdyke, acter, berchem, tudor, leftwood
|
||||
|
||||
### Points of Interest
|
||||
- hospital, police, bowling, cabaret, burgershot, helipad
|
||||
|
||||
## Weather Types
|
||||
|
||||
| ID | Weather |
|
||||
|----|---------|
|
||||
| 0 | Extra Sunny |
|
||||
| 1 | Sunny |
|
||||
| 2 | Sunny Windy |
|
||||
| 3 | Cloudy |
|
||||
| 4 | Raining |
|
||||
| 5 | Drizzle |
|
||||
| 6 | Foggy |
|
||||
| 7 | Thunder |
|
||||
| 8 | Extra Sunny 2 |
|
||||
| 9 | Sunny Windy 2 |
|
||||
|
||||
## Configuration
|
||||
|
||||
### Server Settings (server.xml)
|
||||
|
||||
```xml
|
||||
<servername>Liberty City Freeroam</servername>
|
||||
<maxplayers>32</maxplayers>
|
||||
<port>22000</port>
|
||||
<game>IV</game>
|
||||
```
|
||||
|
||||
### Adding Admins
|
||||
|
||||
Edit `resources/admin/server.js` and add player names to the admins array:
|
||||
|
||||
```javascript
|
||||
const admins = [
|
||||
"YourName",
|
||||
"AnotherAdmin"
|
||||
];
|
||||
```
|
||||
|
||||
## Requirements
|
||||
|
||||
- GTAConnected Server (v1.0.72 or newer)
|
||||
- GTA IV (with Episodes from Liberty City for all vehicles)
|
||||
- Port 22000 UDP forwarded for online play
|
||||
|
||||
## Credits
|
||||
|
||||
- Built for [GTAConnected](https://gtaconnected.com)
|
||||
- Documentation: [GTAConnected Wiki](https://wiki.gtaconnected.com)
|
||||
|
||||
## License
|
||||
|
||||
This project is open source and free to use for your GTA IV multiplayer server.
|
||||
|
||||
5
resources/admin/meta.xml
Normal file
5
resources/admin/meta.xml
Normal file
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<meta>
|
||||
<info author="GTAConnected Server" type="script" version="1.0.0" description="Admin moderation and management tools" />
|
||||
<script src="server.js" type="server" language="javascript" />
|
||||
</meta>
|
||||
490
resources/admin/server.js
Normal file
490
resources/admin/server.js
Normal file
@@ -0,0 +1,490 @@
|
||||
// ============================================================================
|
||||
// ADMIN RESOURCE - Server Side
|
||||
// Handles server moderation, kick/ban, and admin commands
|
||||
// ============================================================================
|
||||
|
||||
// Admin list - add player names or account identifiers here
|
||||
const admins = [
|
||||
"Admin",
|
||||
"Owner",
|
||||
"ServerOwner"
|
||||
];
|
||||
|
||||
// Ban list (stored in memory - use a database for persistence)
|
||||
let bannedPlayers = [];
|
||||
let mutedPlayers = [];
|
||||
|
||||
// ============================================================================
|
||||
// EVENTS
|
||||
// ============================================================================
|
||||
|
||||
addEventHandler("OnResourceStart", function(event, resource) {
|
||||
console.log("[Admin] Resource started - " + admins.length + " admins configured");
|
||||
});
|
||||
|
||||
addEventHandler("OnPlayerConnect", function(event, client, ip) {
|
||||
// Check if player is banned
|
||||
for (let i = 0; i < bannedPlayers.length; i++) {
|
||||
if (bannedPlayers[i].ip === ip || bannedPlayers[i].name === client.name) {
|
||||
console.log("[Admin] Banned player attempted to connect: " + client.name + " (" + ip + ")");
|
||||
// Kick banned player
|
||||
client.disconnect("You are banned from this server: " + bannedPlayers[i].reason);
|
||||
return;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
addEventHandler("OnPlayerJoined", function(event, client) {
|
||||
if (isAdmin(client)) {
|
||||
messageClient("[ADMIN] You have administrator privileges", client, [255, 100, 100, 255]);
|
||||
}
|
||||
});
|
||||
|
||||
addEventHandler("OnPlayerCommand", function(event, client, command, params) {
|
||||
let cmd = command.toLowerCase();
|
||||
|
||||
// Public commands
|
||||
switch(cmd) {
|
||||
case "admins":
|
||||
showAdmins(client);
|
||||
return;
|
||||
|
||||
case "report":
|
||||
if (params && params.length > 0) {
|
||||
reportPlayer(client, params);
|
||||
} else {
|
||||
messageClient("[USAGE] /report <message>", client, [255, 200, 100, 255]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Admin-only commands
|
||||
if (!isAdmin(client)) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch(cmd) {
|
||||
case "kick":
|
||||
if (params && params.length > 0) {
|
||||
let parts = params.split(" ");
|
||||
let targetName = parts[0];
|
||||
let reason = parts.slice(1).join(" ") || "No reason specified";
|
||||
kickPlayer(client, targetName, reason);
|
||||
} else {
|
||||
messageClient("[USAGE] /kick <player> [reason]", client, [255, 200, 100, 255]);
|
||||
}
|
||||
break;
|
||||
|
||||
case "ban":
|
||||
if (params && params.length > 0) {
|
||||
let parts = params.split(" ");
|
||||
let targetName = parts[0];
|
||||
let reason = parts.slice(1).join(" ") || "No reason specified";
|
||||
banPlayer(client, targetName, reason);
|
||||
} else {
|
||||
messageClient("[USAGE] /ban <player> [reason]", client, [255, 200, 100, 255]);
|
||||
}
|
||||
break;
|
||||
|
||||
case "unban":
|
||||
if (params && params.length > 0) {
|
||||
unbanPlayer(client, params);
|
||||
} else {
|
||||
messageClient("[USAGE] /unban <player>", client, [255, 200, 100, 255]);
|
||||
}
|
||||
break;
|
||||
|
||||
case "mute":
|
||||
if (params && params.length > 0) {
|
||||
mutePlayer(client, params);
|
||||
} else {
|
||||
messageClient("[USAGE] /mute <player>", client, [255, 200, 100, 255]);
|
||||
}
|
||||
break;
|
||||
|
||||
case "unmute":
|
||||
if (params && params.length > 0) {
|
||||
unmutePlayer(client, params);
|
||||
} else {
|
||||
messageClient("[USAGE] /unmute <player>", client, [255, 200, 100, 255]);
|
||||
}
|
||||
break;
|
||||
|
||||
case "freeze":
|
||||
if (params && params.length > 0) {
|
||||
freezePlayer(client, params, true);
|
||||
} else {
|
||||
messageClient("[USAGE] /freeze <player>", client, [255, 200, 100, 255]);
|
||||
}
|
||||
break;
|
||||
|
||||
case "unfreeze":
|
||||
if (params && params.length > 0) {
|
||||
freezePlayer(client, params, false);
|
||||
} else {
|
||||
messageClient("[USAGE] /unfreeze <player>", client, [255, 200, 100, 255]);
|
||||
}
|
||||
break;
|
||||
|
||||
case "slap":
|
||||
if (params && params.length > 0) {
|
||||
slapPlayer(client, params);
|
||||
} else {
|
||||
messageClient("[USAGE] /slap <player>", client, [255, 200, 100, 255]);
|
||||
}
|
||||
break;
|
||||
|
||||
case "goto":
|
||||
case "tpto":
|
||||
if (params && params.length > 0) {
|
||||
teleportToPlayer(client, params);
|
||||
} else {
|
||||
messageClient("[USAGE] /goto <player>", client, [255, 200, 100, 255]);
|
||||
}
|
||||
break;
|
||||
|
||||
case "bring":
|
||||
case "tphere":
|
||||
if (params && params.length > 0) {
|
||||
bringPlayer(client, params);
|
||||
} else {
|
||||
messageClient("[USAGE] /bring <player>", client, [255, 200, 100, 255]);
|
||||
}
|
||||
break;
|
||||
|
||||
case "announce":
|
||||
case "ann":
|
||||
if (params && params.length > 0) {
|
||||
announce(params);
|
||||
} else {
|
||||
messageClient("[USAGE] /announce <message>", client, [255, 200, 100, 255]);
|
||||
}
|
||||
break;
|
||||
|
||||
case "setadmin":
|
||||
if (params && params.length > 0) {
|
||||
setAdmin(client, params);
|
||||
} else {
|
||||
messageClient("[USAGE] /setadmin <player>", client, [255, 200, 100, 255]);
|
||||
}
|
||||
break;
|
||||
|
||||
case "getip":
|
||||
if (params && params.length > 0) {
|
||||
getPlayerIP(client, params);
|
||||
} else {
|
||||
messageClient("[USAGE] /getip <player>", client, [255, 200, 100, 255]);
|
||||
}
|
||||
break;
|
||||
|
||||
case "ahelp":
|
||||
case "adminhelp":
|
||||
showAdminHelp(client);
|
||||
break;
|
||||
|
||||
case "sethealth":
|
||||
if (params && params.length > 0) {
|
||||
let parts = params.split(" ");
|
||||
if (parts.length >= 2) {
|
||||
setPlayerHealth(client, parts[0], parseInt(parts[1]));
|
||||
} else {
|
||||
messageClient("[USAGE] /sethealth <player> <health>", client, [255, 200, 100, 255]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case "setarmour":
|
||||
if (params && params.length > 0) {
|
||||
let parts = params.split(" ");
|
||||
if (parts.length >= 2) {
|
||||
setPlayerArmour(client, parts[0], parseInt(parts[1]));
|
||||
} else {
|
||||
messageClient("[USAGE] /setarmour <player> <armour>", client, [255, 200, 100, 255]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case "explode":
|
||||
if (params && params.length > 0) {
|
||||
explodePlayer(client, params);
|
||||
} else {
|
||||
messageClient("[USAGE] /explode <player>", client, [255, 200, 100, 255]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
// Check if player is muted before chat
|
||||
addEventHandler("OnPlayerChat", function(event, client, messageText) {
|
||||
if (isMuted(client)) {
|
||||
messageClient("[ADMIN] You are muted and cannot chat!", client, [255, 100, 100, 255]);
|
||||
return false; // Cancel the chat
|
||||
}
|
||||
});
|
||||
|
||||
// ============================================================================
|
||||
// FUNCTIONS
|
||||
// ============================================================================
|
||||
|
||||
function isAdmin(client) {
|
||||
return admins.indexOf(client.name) !== -1;
|
||||
}
|
||||
|
||||
function isMuted(client) {
|
||||
return mutedPlayers.indexOf(client.name) !== -1;
|
||||
}
|
||||
|
||||
function findPlayer(name) {
|
||||
let clients = getClients();
|
||||
let nameLower = name.toLowerCase();
|
||||
|
||||
for (let i = 0; i < clients.length; i++) {
|
||||
if (clients[i].name.toLowerCase() === nameLower ||
|
||||
clients[i].name.toLowerCase().indexOf(nameLower) !== -1) {
|
||||
return clients[i];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function kickPlayer(admin, targetName, reason) {
|
||||
let target = findPlayer(targetName);
|
||||
if (target) {
|
||||
message("[ADMIN] " + target.name + " was kicked by " + admin.name + ": " + reason, [255, 100, 100, 255]);
|
||||
target.disconnect("Kicked: " + reason);
|
||||
console.log("[Admin] " + admin.name + " kicked " + target.name + ": " + reason);
|
||||
} else {
|
||||
messageClient("[ADMIN] Player not found: " + targetName, admin, [255, 100, 100, 255]);
|
||||
}
|
||||
}
|
||||
|
||||
function banPlayer(admin, targetName, reason) {
|
||||
let target = findPlayer(targetName);
|
||||
if (target) {
|
||||
bannedPlayers.push({
|
||||
name: target.name,
|
||||
ip: target.ip,
|
||||
reason: reason,
|
||||
admin: admin.name,
|
||||
date: new Date().toISOString()
|
||||
});
|
||||
|
||||
message("[ADMIN] " + target.name + " was banned by " + admin.name + ": " + reason, [255, 50, 50, 255]);
|
||||
target.disconnect("Banned: " + reason);
|
||||
console.log("[Admin] " + admin.name + " banned " + target.name + ": " + reason);
|
||||
} else {
|
||||
messageClient("[ADMIN] Player not found: " + targetName, admin, [255, 100, 100, 255]);
|
||||
}
|
||||
}
|
||||
|
||||
function unbanPlayer(admin, targetName) {
|
||||
let found = false;
|
||||
for (let i = bannedPlayers.length - 1; i >= 0; i--) {
|
||||
if (bannedPlayers[i].name.toLowerCase() === targetName.toLowerCase()) {
|
||||
bannedPlayers.splice(i, 1);
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (found) {
|
||||
messageClient("[ADMIN] " + targetName + " has been unbanned", admin, [100, 255, 100, 255]);
|
||||
console.log("[Admin] " + admin.name + " unbanned " + targetName);
|
||||
} else {
|
||||
messageClient("[ADMIN] Player not found in ban list: " + targetName, admin, [255, 100, 100, 255]);
|
||||
}
|
||||
}
|
||||
|
||||
function mutePlayer(admin, targetName) {
|
||||
let target = findPlayer(targetName);
|
||||
if (target) {
|
||||
if (mutedPlayers.indexOf(target.name) === -1) {
|
||||
mutedPlayers.push(target.name);
|
||||
}
|
||||
message("[ADMIN] " + target.name + " was muted by " + admin.name, [255, 150, 100, 255]);
|
||||
console.log("[Admin] " + admin.name + " muted " + target.name);
|
||||
} else {
|
||||
messageClient("[ADMIN] Player not found: " + targetName, admin, [255, 100, 100, 255]);
|
||||
}
|
||||
}
|
||||
|
||||
function unmutePlayer(admin, targetName) {
|
||||
let target = findPlayer(targetName);
|
||||
let name = target ? target.name : targetName;
|
||||
|
||||
let index = mutedPlayers.indexOf(name);
|
||||
if (index !== -1) {
|
||||
mutedPlayers.splice(index, 1);
|
||||
message("[ADMIN] " + name + " was unmuted by " + admin.name, [100, 255, 100, 255]);
|
||||
console.log("[Admin] " + admin.name + " unmuted " + name);
|
||||
} else {
|
||||
messageClient("[ADMIN] Player is not muted: " + targetName, admin, [255, 100, 100, 255]);
|
||||
}
|
||||
}
|
||||
|
||||
function freezePlayer(admin, targetName, freeze) {
|
||||
let target = findPlayer(targetName);
|
||||
if (target && target.player) {
|
||||
target.player.frozen = freeze;
|
||||
let status = freeze ? "frozen" : "unfrozen";
|
||||
message("[ADMIN] " + target.name + " was " + status + " by " + admin.name, [255, 200, 100, 255]);
|
||||
console.log("[Admin] " + admin.name + " " + status + " " + target.name);
|
||||
} else {
|
||||
messageClient("[ADMIN] Player not found: " + targetName, admin, [255, 100, 100, 255]);
|
||||
}
|
||||
}
|
||||
|
||||
function slapPlayer(admin, targetName) {
|
||||
let target = findPlayer(targetName);
|
||||
if (target && target.player) {
|
||||
let pos = target.player.position;
|
||||
target.player.position = [pos[0], pos[1], pos[2] + 5]; // Launch up
|
||||
target.player.health -= 10;
|
||||
message("[ADMIN] " + target.name + " was slapped by " + admin.name, [255, 200, 100, 255]);
|
||||
console.log("[Admin] " + admin.name + " slapped " + target.name);
|
||||
} else {
|
||||
messageClient("[ADMIN] Player not found: " + targetName, admin, [255, 100, 100, 255]);
|
||||
}
|
||||
}
|
||||
|
||||
function teleportToPlayer(admin, targetName) {
|
||||
let target = findPlayer(targetName);
|
||||
if (target && target.player && admin.player) {
|
||||
let pos = target.player.position;
|
||||
admin.player.position = [pos[0] + 2, pos[1], pos[2]];
|
||||
messageClient("[ADMIN] Teleported to " + target.name, admin, [100, 255, 100, 255]);
|
||||
console.log("[Admin] " + admin.name + " teleported to " + target.name);
|
||||
} else {
|
||||
messageClient("[ADMIN] Player not found: " + targetName, admin, [255, 100, 100, 255]);
|
||||
}
|
||||
}
|
||||
|
||||
function bringPlayer(admin, targetName) {
|
||||
let target = findPlayer(targetName);
|
||||
if (target && target.player && admin.player) {
|
||||
let pos = admin.player.position;
|
||||
target.player.position = [pos[0] + 2, pos[1], pos[2]];
|
||||
messageClient("[ADMIN] " + admin.name + " brought you to them", target, [255, 200, 100, 255]);
|
||||
messageClient("[ADMIN] Brought " + target.name + " to you", admin, [100, 255, 100, 255]);
|
||||
console.log("[Admin] " + admin.name + " brought " + target.name);
|
||||
} else {
|
||||
messageClient("[ADMIN] Player not found: " + targetName, admin, [255, 100, 100, 255]);
|
||||
}
|
||||
}
|
||||
|
||||
function announce(text) {
|
||||
message("=================================", [255, 255, 100, 255]);
|
||||
message("[ANNOUNCEMENT] " + text, [255, 255, 100, 255]);
|
||||
message("=================================", [255, 255, 100, 255]);
|
||||
console.log("[Admin] Announcement: " + text);
|
||||
}
|
||||
|
||||
function setAdmin(admin, targetName) {
|
||||
let target = findPlayer(targetName);
|
||||
if (target) {
|
||||
if (admins.indexOf(target.name) === -1) {
|
||||
admins.push(target.name);
|
||||
messageClient("[ADMIN] You have been granted admin privileges by " + admin.name, target, [100, 255, 100, 255]);
|
||||
messageClient("[ADMIN] " + target.name + " is now an admin", admin, [100, 255, 100, 255]);
|
||||
console.log("[Admin] " + admin.name + " made " + target.name + " an admin");
|
||||
} else {
|
||||
messageClient("[ADMIN] " + target.name + " is already an admin", admin, [255, 200, 100, 255]);
|
||||
}
|
||||
} else {
|
||||
messageClient("[ADMIN] Player not found: " + targetName, admin, [255, 100, 100, 255]);
|
||||
}
|
||||
}
|
||||
|
||||
function getPlayerIP(admin, targetName) {
|
||||
let target = findPlayer(targetName);
|
||||
if (target) {
|
||||
messageClient("[ADMIN] " + target.name + "'s IP: " + target.ip, admin, [200, 200, 255, 255]);
|
||||
} else {
|
||||
messageClient("[ADMIN] Player not found: " + targetName, admin, [255, 100, 100, 255]);
|
||||
}
|
||||
}
|
||||
|
||||
function setPlayerHealth(admin, targetName, health) {
|
||||
let target = findPlayer(targetName);
|
||||
if (target && target.player) {
|
||||
target.player.health = health;
|
||||
messageClient("[ADMIN] Set " + target.name + "'s health to " + health, admin, [100, 255, 100, 255]);
|
||||
} else {
|
||||
messageClient("[ADMIN] Player not found: " + targetName, admin, [255, 100, 100, 255]);
|
||||
}
|
||||
}
|
||||
|
||||
function setPlayerArmour(admin, targetName, armour) {
|
||||
let target = findPlayer(targetName);
|
||||
if (target && target.player) {
|
||||
target.player.armour = armour;
|
||||
messageClient("[ADMIN] Set " + target.name + "'s armour to " + armour, admin, [100, 255, 100, 255]);
|
||||
} else {
|
||||
messageClient("[ADMIN] Player not found: " + targetName, admin, [255, 100, 100, 255]);
|
||||
}
|
||||
}
|
||||
|
||||
function explodePlayer(admin, targetName) {
|
||||
let target = findPlayer(targetName);
|
||||
if (target && target.player) {
|
||||
let pos = target.player.position;
|
||||
gta.createExplosion(pos, 0, 10.0);
|
||||
message("[ADMIN] " + target.name + " was exploded by " + admin.name, [255, 100, 100, 255]);
|
||||
console.log("[Admin] " + admin.name + " exploded " + target.name);
|
||||
} else {
|
||||
messageClient("[ADMIN] Player not found: " + targetName, admin, [255, 100, 100, 255]);
|
||||
}
|
||||
}
|
||||
|
||||
function showAdmins(client) {
|
||||
messageClient("=== ONLINE ADMINS ===", client, [255, 200, 100, 255]);
|
||||
let clients = getClients();
|
||||
let onlineAdmins = [];
|
||||
|
||||
for (let i = 0; i < clients.length; i++) {
|
||||
if (isAdmin(clients[i])) {
|
||||
onlineAdmins.push(clients[i].name);
|
||||
}
|
||||
}
|
||||
|
||||
if (onlineAdmins.length > 0) {
|
||||
messageClient(onlineAdmins.join(", "), client, [100, 255, 100, 255]);
|
||||
} else {
|
||||
messageClient("No admins online", client, [200, 200, 200, 255]);
|
||||
}
|
||||
}
|
||||
|
||||
function reportPlayer(client, reportMessage) {
|
||||
let clients = getClients();
|
||||
console.log("[Report] " + client.name + ": " + reportMessage);
|
||||
|
||||
// Notify all online admins
|
||||
for (let i = 0; i < clients.length; i++) {
|
||||
if (isAdmin(clients[i])) {
|
||||
messageClient("[REPORT] " + client.name + ": " + reportMessage, clients[i], [255, 200, 100, 255]);
|
||||
}
|
||||
}
|
||||
|
||||
messageClient("[REPORT] Your report has been sent to admins", client, [100, 255, 100, 255]);
|
||||
}
|
||||
|
||||
function showAdminHelp(client) {
|
||||
messageClient("=== ADMIN COMMANDS ===", client, [255, 200, 100, 255]);
|
||||
messageClient("/kick <player> [reason] - Kick a player", client, [200, 200, 200, 255]);
|
||||
messageClient("/ban <player> [reason] - Ban a player", client, [200, 200, 200, 255]);
|
||||
messageClient("/unban <player> - Unban a player", client, [200, 200, 200, 255]);
|
||||
messageClient("/mute <player> - Mute a player", client, [200, 200, 200, 255]);
|
||||
messageClient("/unmute <player> - Unmute a player", client, [200, 200, 200, 255]);
|
||||
messageClient("/freeze <player> - Freeze a player", client, [200, 200, 200, 255]);
|
||||
messageClient("/unfreeze <player> - Unfreeze a player", client, [200, 200, 200, 255]);
|
||||
messageClient("/slap <player> - Slap a player", client, [200, 200, 200, 255]);
|
||||
messageClient("/goto <player> - Teleport to a player", client, [200, 200, 200, 255]);
|
||||
messageClient("/bring <player> - Bring a player to you", client, [200, 200, 200, 255]);
|
||||
messageClient("/announce <msg> - Server announcement", client, [200, 200, 200, 255]);
|
||||
messageClient("/setadmin <player> - Grant admin rights", client, [200, 200, 200, 255]);
|
||||
messageClient("/getip <player> - Get player's IP", client, [200, 200, 200, 255]);
|
||||
messageClient("/sethealth <player> <hp> - Set health", client, [200, 200, 200, 255]);
|
||||
messageClient("/setarmour <player> <armor> - Set armour", client, [200, 200, 200, 255]);
|
||||
messageClient("/explode <player> - Explode a player", client, [200, 200, 200, 255]);
|
||||
}
|
||||
|
||||
console.log("[Admin] Server script loaded!");
|
||||
5
resources/chat/meta.xml
Normal file
5
resources/chat/meta.xml
Normal file
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<meta>
|
||||
<info author="GTAConnected Server" type="script" version="1.0.0" description="Enhanced chat system with colors and features" />
|
||||
<script src="server.js" type="server" language="javascript" />
|
||||
</meta>
|
||||
246
resources/chat/server.js
Normal file
246
resources/chat/server.js
Normal file
@@ -0,0 +1,246 @@
|
||||
// ============================================================================
|
||||
// CHAT RESOURCE - Server Side
|
||||
// Enhanced chat system with private messages, colors, and special features
|
||||
// ============================================================================
|
||||
|
||||
// Chat colors for different message types
|
||||
const chatColors = {
|
||||
normal: [255, 255, 255, 255],
|
||||
action: [200, 100, 255, 255],
|
||||
whisper: [255, 255, 100, 255],
|
||||
shout: [255, 100, 100, 255],
|
||||
ooc: [150, 150, 150, 255],
|
||||
admin: [255, 100, 100, 255],
|
||||
system: [100, 200, 255, 255]
|
||||
};
|
||||
|
||||
// Chat history (for logging purposes)
|
||||
let chatHistory = [];
|
||||
const maxHistory = 100;
|
||||
|
||||
// ============================================================================
|
||||
// EVENTS
|
||||
// ============================================================================
|
||||
|
||||
addEventHandler("OnResourceStart", function(event, resource) {
|
||||
console.log("[Chat] Resource started");
|
||||
});
|
||||
|
||||
addEventHandler("OnPlayerChat", function(event, client, messageText) {
|
||||
// Format and broadcast the chat message
|
||||
let formattedMessage = client.name + ": " + messageText;
|
||||
message(formattedMessage, chatColors.normal);
|
||||
|
||||
// Log to history
|
||||
logChat(client.name, messageText, "chat");
|
||||
|
||||
// Prevent default chat handling
|
||||
return false;
|
||||
});
|
||||
|
||||
addEventHandler("OnPlayerCommand", function(event, client, command, params) {
|
||||
let cmd = command.toLowerCase();
|
||||
|
||||
switch(cmd) {
|
||||
case "pm":
|
||||
case "msg":
|
||||
case "whisper":
|
||||
case "w":
|
||||
if (params && params.length > 0) {
|
||||
let parts = params.split(" ");
|
||||
let targetName = parts[0];
|
||||
let messageText = parts.slice(1).join(" ");
|
||||
|
||||
if (messageText.length > 0) {
|
||||
sendPrivateMessage(client, targetName, messageText);
|
||||
} else {
|
||||
messageClient("[USAGE] /pm <player> <message>", client, [255, 200, 100, 255]);
|
||||
}
|
||||
} else {
|
||||
messageClient("[USAGE] /pm <player> <message>", client, [255, 200, 100, 255]);
|
||||
}
|
||||
break;
|
||||
|
||||
case "me":
|
||||
case "action":
|
||||
if (params && params.length > 0) {
|
||||
let actionMessage = "* " + client.name + " " + params;
|
||||
message(actionMessage, chatColors.action);
|
||||
logChat(client.name, params, "action");
|
||||
} else {
|
||||
messageClient("[USAGE] /me <action>", client, [255, 200, 100, 255]);
|
||||
}
|
||||
break;
|
||||
|
||||
case "do":
|
||||
if (params && params.length > 0) {
|
||||
let doMessage = "* " + params + " (" + client.name + ")";
|
||||
message(doMessage, chatColors.action);
|
||||
logChat(client.name, params, "do");
|
||||
} else {
|
||||
messageClient("[USAGE] /do <description>", client, [255, 200, 100, 255]);
|
||||
}
|
||||
break;
|
||||
|
||||
case "shout":
|
||||
case "s":
|
||||
if (params && params.length > 0) {
|
||||
let shoutMessage = client.name + " shouts: " + params.toUpperCase() + "!";
|
||||
message(shoutMessage, chatColors.shout);
|
||||
logChat(client.name, params, "shout");
|
||||
} else {
|
||||
messageClient("[USAGE] /shout <message>", client, [255, 200, 100, 255]);
|
||||
}
|
||||
break;
|
||||
|
||||
case "ooc":
|
||||
case "b":
|
||||
if (params && params.length > 0) {
|
||||
let oocMessage = "(( " + client.name + ": " + params + " ))";
|
||||
message(oocMessage, chatColors.ooc);
|
||||
logChat(client.name, params, "ooc");
|
||||
} else {
|
||||
messageClient("[USAGE] /ooc <message>", client, [255, 200, 100, 255]);
|
||||
}
|
||||
break;
|
||||
|
||||
case "local":
|
||||
case "l":
|
||||
if (params && params.length > 0) {
|
||||
sendLocalMessage(client, params);
|
||||
} else {
|
||||
messageClient("[USAGE] /local <message>", client, [255, 200, 100, 255]);
|
||||
}
|
||||
break;
|
||||
|
||||
case "reply":
|
||||
case "r":
|
||||
if (params && params.length > 0) {
|
||||
replyToLastPM(client, params);
|
||||
} else {
|
||||
messageClient("[USAGE] /r <message>", client, [255, 200, 100, 255]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
// ============================================================================
|
||||
// FUNCTIONS
|
||||
// ============================================================================
|
||||
|
||||
// Store last PM sender for reply function
|
||||
let lastPMSender = {};
|
||||
|
||||
function sendPrivateMessage(sender, targetName, messageText) {
|
||||
let target = findPlayer(targetName);
|
||||
|
||||
if (target) {
|
||||
if (target.index === sender.index) {
|
||||
messageClient("[PM] You cannot message yourself!", sender, [255, 100, 100, 255]);
|
||||
return;
|
||||
}
|
||||
|
||||
// Send to target
|
||||
messageClient("[PM from " + sender.name + "]: " + messageText, target, chatColors.whisper);
|
||||
|
||||
// Confirm to sender
|
||||
messageClient("[PM to " + target.name + "]: " + messageText, sender, chatColors.whisper);
|
||||
|
||||
// Store for reply function
|
||||
lastPMSender[target.index] = sender.index;
|
||||
|
||||
logChat(sender.name, "-> " + target.name + ": " + messageText, "pm");
|
||||
} else {
|
||||
messageClient("[PM] Player not found: " + targetName, sender, [255, 100, 100, 255]);
|
||||
}
|
||||
}
|
||||
|
||||
function replyToLastPM(client, messageText) {
|
||||
if (lastPMSender[client.index] !== undefined) {
|
||||
let targetIndex = lastPMSender[client.index];
|
||||
let clients = getClients();
|
||||
let target = null;
|
||||
|
||||
for (let i = 0; i < clients.length; i++) {
|
||||
if (clients[i].index === targetIndex) {
|
||||
target = clients[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (target) {
|
||||
sendPrivateMessage(client, target.name, messageText);
|
||||
} else {
|
||||
messageClient("[PM] The player you're trying to reply to is no longer online", client, [255, 100, 100, 255]);
|
||||
}
|
||||
} else {
|
||||
messageClient("[PM] No one has messaged you yet", client, [255, 100, 100, 255]);
|
||||
}
|
||||
}
|
||||
|
||||
function sendLocalMessage(sender, messageText) {
|
||||
if (!sender.player) {
|
||||
messageClient("[LOCAL] You need to spawn first!", sender, [255, 100, 100, 255]);
|
||||
return;
|
||||
}
|
||||
|
||||
let senderPos = sender.player.position;
|
||||
let localRange = 30.0; // 30 units range for local chat
|
||||
let clients = getClients();
|
||||
|
||||
// Send to nearby players
|
||||
for (let i = 0; i < clients.length; i++) {
|
||||
let client = clients[i];
|
||||
if (client.player) {
|
||||
let clientPos = client.player.position;
|
||||
let distance = getDistance(senderPos, clientPos);
|
||||
|
||||
if (distance <= localRange) {
|
||||
let localMessage = "(Local) " + sender.name + ": " + messageText;
|
||||
messageClient(localMessage, client, [200, 255, 200, 255]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
logChat(sender.name, messageText, "local");
|
||||
}
|
||||
|
||||
function findPlayer(name) {
|
||||
let clients = getClients();
|
||||
let nameLower = name.toLowerCase();
|
||||
|
||||
for (let i = 0; i < clients.length; i++) {
|
||||
if (clients[i].name.toLowerCase() === nameLower ||
|
||||
clients[i].name.toLowerCase().indexOf(nameLower) !== -1) {
|
||||
return clients[i];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function getDistance(pos1, pos2) {
|
||||
let dx = pos1[0] - pos2[0];
|
||||
let dy = pos1[1] - pos2[1];
|
||||
let dz = pos1[2] - pos2[2];
|
||||
return Math.sqrt(dx * dx + dy * dy + dz * dz);
|
||||
}
|
||||
|
||||
function logChat(playerName, messageText, type) {
|
||||
let entry = {
|
||||
time: new Date().toISOString(),
|
||||
player: playerName,
|
||||
message: messageText,
|
||||
type: type
|
||||
};
|
||||
|
||||
chatHistory.push(entry);
|
||||
|
||||
// Keep history limited
|
||||
if (chatHistory.length > maxHistory) {
|
||||
chatHistory.shift();
|
||||
}
|
||||
|
||||
console.log("[Chat][" + type + "] " + playerName + ": " + messageText);
|
||||
}
|
||||
|
||||
console.log("[Chat] Server script loaded!");
|
||||
41
resources/freeroam/client.js
Normal file
41
resources/freeroam/client.js
Normal file
@@ -0,0 +1,41 @@
|
||||
// ============================================================================
|
||||
// FREEROAM RESOURCE - Client Side
|
||||
// Handles camera fade, HUD elements, and client-side features
|
||||
// ============================================================================
|
||||
|
||||
// When the resource starts on client
|
||||
addEventHandler("OnResourceStart", function(event, resource) {
|
||||
console.log("[Freeroam] Client resource started");
|
||||
});
|
||||
|
||||
// When local player spawns
|
||||
addEventHandler("OnLocalPlayerSpawn", function(event) {
|
||||
console.log("[Freeroam] Local player spawned");
|
||||
|
||||
// Fade in the camera
|
||||
gta.fadeCamera(true, 1.0);
|
||||
|
||||
// Show welcome message
|
||||
gta.showMessage("Welcome to Liberty City!", 5000);
|
||||
});
|
||||
|
||||
// Process event for continuous updates
|
||||
addEventHandler("OnProcess", function(event) {
|
||||
// Can be used for HUD updates, etc.
|
||||
});
|
||||
|
||||
// When player enters a vehicle
|
||||
addEventHandler("OnPedEnterVehicle", function(event, ped, vehicle, seat) {
|
||||
if (ped == localPlayer) {
|
||||
console.log("[Freeroam] Player entered vehicle");
|
||||
}
|
||||
});
|
||||
|
||||
// When player exits a vehicle
|
||||
addEventHandler("OnPedExitVehicle", function(event, ped, vehicle, seat) {
|
||||
if (ped == localPlayer) {
|
||||
console.log("[Freeroam] Player exited vehicle");
|
||||
}
|
||||
});
|
||||
|
||||
console.log("[Freeroam] Client script loaded!");
|
||||
6
resources/freeroam/meta.xml
Normal file
6
resources/freeroam/meta.xml
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<meta>
|
||||
<info author="GTAConnected Server" type="script" version="1.0.0" description="Freeroam spawn and player management system" />
|
||||
<script src="server.js" type="server" language="javascript" />
|
||||
<script src="client.js" type="client" language="javascript" />
|
||||
</meta>
|
||||
331
resources/freeroam/server.js
Normal file
331
resources/freeroam/server.js
Normal file
@@ -0,0 +1,331 @@
|
||||
// ============================================================================
|
||||
// FREEROAM RESOURCE - Server Side
|
||||
// Handles player spawning, basic commands, and player management
|
||||
// ============================================================================
|
||||
|
||||
// Spawn points around Liberty City (GTA IV)
|
||||
const spawnPoints = [
|
||||
{ x: -252.0, y: 947.0, z: 15.0, name: "Star Junction" },
|
||||
{ x: 932.0, y: -495.0, z: 15.0, name: "Broker Bridge" },
|
||||
{ x: -365.0, y: 1163.0, z: 14.0, name: "Middle Park" },
|
||||
{ x: 1243.0, y: -196.0, z: 26.0, name: "Bohan" },
|
||||
{ x: -1149.0, y: 380.0, z: 21.0, name: "Alderney" },
|
||||
{ x: 237.0, y: 1002.0, z: 18.0, name: "Rotterdam Tower" },
|
||||
{ x: -429.0, y: 1494.0, z: 11.0, name: "North Holland" },
|
||||
{ x: 858.0, y: 279.0, z: 30.0, name: "East Borough Bridge" }
|
||||
];
|
||||
|
||||
// Player skins for GTA IV
|
||||
const playerSkins = [
|
||||
-1667301416, // Niko Bellic
|
||||
-163448165, // Roman Bellic
|
||||
1936355839, // Little Jacob
|
||||
-1938475496, // Brucie
|
||||
970234525, // Playboy X
|
||||
-1784875845, // Johnny Klebitz
|
||||
-1403507487, // Luis Lopez
|
||||
];
|
||||
|
||||
// Store player data
|
||||
let playerData = {};
|
||||
|
||||
// ============================================================================
|
||||
// EVENTS
|
||||
// ============================================================================
|
||||
|
||||
// When resource starts
|
||||
addEventHandler("OnResourceStart", function(event, resource) {
|
||||
console.log("[Freeroam] Resource started successfully!");
|
||||
console.log("[Freeroam] " + spawnPoints.length + " spawn points loaded");
|
||||
});
|
||||
|
||||
// When a player connects
|
||||
addEventHandler("OnPlayerConnect", function(event, client, ip) {
|
||||
console.log("[Freeroam] Player connecting: " + ip);
|
||||
});
|
||||
|
||||
// When a player joins
|
||||
addEventHandler("OnPlayerJoined", function(event, client) {
|
||||
console.log("[Freeroam] Player joined: " + client.name);
|
||||
|
||||
// Initialize player data
|
||||
playerData[client.index] = {
|
||||
spawned: false,
|
||||
kills: 0,
|
||||
deaths: 0,
|
||||
money: 5000,
|
||||
health: 100,
|
||||
armour: 0
|
||||
};
|
||||
|
||||
// Welcome message
|
||||
messageClient("[SERVER] Welcome to Liberty City Freeroam, " + client.name + "!", client, [255, 200, 100, 255]);
|
||||
messageClient("[SERVER] Type /help for available commands", client, [200, 200, 200, 255]);
|
||||
|
||||
// Spawn the player
|
||||
spawnPlayer(client);
|
||||
});
|
||||
|
||||
// When a player quits
|
||||
addEventHandler("OnPlayerQuit", function(event, client, reason) {
|
||||
console.log("[Freeroam] Player quit: " + client.name + " - Reason: " + reason);
|
||||
|
||||
// Broadcast quit message
|
||||
message("[SERVER] " + client.name + " has left the server", [255, 150, 100, 255]);
|
||||
|
||||
// Clean up player data
|
||||
delete playerData[client.index];
|
||||
});
|
||||
|
||||
// When a player dies (gets wasted)
|
||||
addEventHandler("OnPedWasted", function(event, ped, killer, weapon) {
|
||||
// Check if the ped belongs to a player
|
||||
let client = getClientFromPed(ped);
|
||||
if (client) {
|
||||
if (playerData[client.index]) {
|
||||
playerData[client.index].deaths++;
|
||||
}
|
||||
|
||||
// Check if killed by another player
|
||||
if (killer) {
|
||||
let killerClient = getClientFromPed(killer);
|
||||
if (killerClient && playerData[killerClient.index]) {
|
||||
playerData[killerClient.index].kills++;
|
||||
message("[KILL] " + killerClient.name + " killed " + client.name, [255, 100, 100, 255]);
|
||||
}
|
||||
}
|
||||
|
||||
// Respawn after delay
|
||||
setTimeout(function() {
|
||||
if (client && client.player) {
|
||||
spawnPlayer(client);
|
||||
}
|
||||
}, 3000);
|
||||
}
|
||||
});
|
||||
|
||||
// When a player sends a command
|
||||
addEventHandler("OnPlayerCommand", function(event, client, command, params) {
|
||||
let cmd = command.toLowerCase();
|
||||
|
||||
switch(cmd) {
|
||||
case "help":
|
||||
showHelp(client);
|
||||
break;
|
||||
|
||||
case "spawn":
|
||||
case "respawn":
|
||||
spawnPlayer(client);
|
||||
messageClient("[SERVER] You have been respawned!", client, [100, 255, 100, 255]);
|
||||
break;
|
||||
|
||||
case "kill":
|
||||
case "suicide":
|
||||
if (client.player) {
|
||||
client.player.health = 0;
|
||||
messageClient("[SERVER] You killed yourself!", client, [255, 100, 100, 255]);
|
||||
}
|
||||
break;
|
||||
|
||||
case "pos":
|
||||
case "position":
|
||||
if (client.player) {
|
||||
let pos = client.player.position;
|
||||
messageClient("[POS] X: " + pos[0].toFixed(2) + " Y: " + pos[1].toFixed(2) + " Z: " + pos[2].toFixed(2), client, [200, 200, 255, 255]);
|
||||
}
|
||||
break;
|
||||
|
||||
case "stats":
|
||||
showStats(client);
|
||||
break;
|
||||
|
||||
case "players":
|
||||
case "online":
|
||||
showOnlinePlayers(client);
|
||||
break;
|
||||
|
||||
case "heal":
|
||||
if (client.player) {
|
||||
client.player.health = 100;
|
||||
messageClient("[SERVER] You have been healed!", client, [100, 255, 100, 255]);
|
||||
}
|
||||
break;
|
||||
|
||||
case "armour":
|
||||
case "armor":
|
||||
if (client.player) {
|
||||
client.player.armour = 100;
|
||||
messageClient("[SERVER] You have been given armour!", client, [100, 200, 255, 255]);
|
||||
}
|
||||
break;
|
||||
|
||||
case "skin":
|
||||
if (params && params.length > 0) {
|
||||
let skinId = parseInt(params);
|
||||
if (!isNaN(skinId)) {
|
||||
if (client.player) {
|
||||
client.player.modelIndex = skinId;
|
||||
messageClient("[SERVER] Skin changed to: " + skinId, client, [200, 200, 255, 255]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
messageClient("[USAGE] /skin <skin_id>", client, [255, 200, 100, 255]);
|
||||
}
|
||||
break;
|
||||
|
||||
case "weapons":
|
||||
case "giveweapons":
|
||||
giveWeapons(client);
|
||||
messageClient("[SERVER] You have been given weapons!", client, [255, 200, 100, 255]);
|
||||
break;
|
||||
|
||||
case "flip":
|
||||
if (client.player && client.player.vehicle) {
|
||||
let veh = client.player.vehicle;
|
||||
let rot = veh.rotation;
|
||||
veh.rotation = [0, 0, rot[2]];
|
||||
messageClient("[SERVER] Vehicle flipped!", client, [100, 255, 100, 255]);
|
||||
} else {
|
||||
messageClient("[SERVER] You need to be in a vehicle!", client, [255, 100, 100, 255]);
|
||||
}
|
||||
break;
|
||||
|
||||
case "fix":
|
||||
case "repair":
|
||||
if (client.player && client.player.vehicle) {
|
||||
client.player.vehicle.health = 1000;
|
||||
messageClient("[SERVER] Vehicle repaired!", client, [100, 255, 100, 255]);
|
||||
} else {
|
||||
messageClient("[SERVER] You need to be in a vehicle!", client, [255, 100, 100, 255]);
|
||||
}
|
||||
break;
|
||||
|
||||
case "eject":
|
||||
if (client.player && client.player.vehicle) {
|
||||
client.player.removeFromVehicle();
|
||||
messageClient("[SERVER] Ejected from vehicle!", client, [200, 200, 255, 255]);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
// Unknown command handled by other resources
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
// ============================================================================
|
||||
// FUNCTIONS
|
||||
// ============================================================================
|
||||
|
||||
function spawnPlayer(client) {
|
||||
// Select random spawn point
|
||||
let spawn = spawnPoints[Math.floor(Math.random() * spawnPoints.length)];
|
||||
|
||||
// Select random skin
|
||||
let skin = playerSkins[Math.floor(Math.random() * playerSkins.length)];
|
||||
|
||||
// Spawn the player
|
||||
client.spawn([spawn.x, spawn.y, spawn.z], 0, skin);
|
||||
|
||||
// Give basic weapons after short delay
|
||||
setTimeout(function() {
|
||||
if (client && client.player) {
|
||||
giveStarterWeapons(client);
|
||||
}
|
||||
}, 1000);
|
||||
|
||||
if (playerData[client.index]) {
|
||||
playerData[client.index].spawned = true;
|
||||
}
|
||||
|
||||
console.log("[Freeroam] Spawned " + client.name + " at " + spawn.name);
|
||||
}
|
||||
|
||||
function giveStarterWeapons(client) {
|
||||
if (!client || !client.player) return;
|
||||
|
||||
// Give basic starter weapons (GTA IV weapon IDs)
|
||||
// Pistol
|
||||
client.giveWeapon(5, 100); // Pistol with 100 ammo
|
||||
// SMG
|
||||
client.giveWeapon(11, 200); // Micro SMG with 200 ammo
|
||||
}
|
||||
|
||||
function giveWeapons(client) {
|
||||
if (!client || !client.player) return;
|
||||
|
||||
// GTA IV Weapon IDs
|
||||
client.giveWeapon(1, 1); // Baseball Bat
|
||||
client.giveWeapon(2, 1); // Knife
|
||||
client.giveWeapon(5, 500); // Pistol
|
||||
client.giveWeapon(6, 500); // Desert Eagle
|
||||
client.giveWeapon(9, 200); // Shotgun
|
||||
client.giveWeapon(10, 200); // Combat Shotgun
|
||||
client.giveWeapon(11, 500); // Micro SMG
|
||||
client.giveWeapon(12, 500); // SMG
|
||||
client.giveWeapon(14, 500); // Assault Rifle
|
||||
client.giveWeapon(15, 500); // Carbine Rifle
|
||||
client.giveWeapon(16, 100); // Sniper Rifle
|
||||
client.giveWeapon(18, 20); // RPG
|
||||
client.giveWeapon(19, 20); // Grenades
|
||||
client.giveWeapon(20, 20); // Molotov
|
||||
}
|
||||
|
||||
function showHelp(client) {
|
||||
messageClient("=== AVAILABLE COMMANDS ===", client, [255, 200, 100, 255]);
|
||||
messageClient("/spawn - Respawn at a random location", client, [200, 200, 200, 255]);
|
||||
messageClient("/kill - Kill yourself", client, [200, 200, 200, 255]);
|
||||
messageClient("/pos - Show your current position", client, [200, 200, 200, 255]);
|
||||
messageClient("/stats - Show your statistics", client, [200, 200, 200, 255]);
|
||||
messageClient("/players - Show online players", client, [200, 200, 200, 255]);
|
||||
messageClient("/heal - Restore your health", client, [200, 200, 200, 255]);
|
||||
messageClient("/armour - Give yourself armour", client, [200, 200, 200, 255]);
|
||||
messageClient("/weapons - Get all weapons", client, [200, 200, 200, 255]);
|
||||
messageClient("/skin <id> - Change your skin", client, [200, 200, 200, 255]);
|
||||
messageClient("/flip - Flip your vehicle", client, [200, 200, 200, 255]);
|
||||
messageClient("/fix - Repair your vehicle", client, [200, 200, 200, 255]);
|
||||
messageClient("/eject - Exit vehicle", client, [200, 200, 200, 255]);
|
||||
messageClient("=== VEHICLE COMMANDS ===", client, [255, 200, 100, 255]);
|
||||
messageClient("/v <name> - Spawn a vehicle", client, [200, 200, 200, 255]);
|
||||
messageClient("/dv - Delete your vehicle", client, [200, 200, 200, 255]);
|
||||
messageClient("=== TELEPORT COMMANDS ===", client, [255, 200, 100, 255]);
|
||||
messageClient("/tp <location> - Teleport to location", client, [200, 200, 200, 255]);
|
||||
messageClient("/tplist - List teleport locations", client, [200, 200, 200, 255]);
|
||||
messageClient("=== WORLD COMMANDS ===", client, [255, 200, 100, 255]);
|
||||
messageClient("/weather <id> - Change weather", client, [200, 200, 200, 255]);
|
||||
messageClient("/time <hour> - Change time", client, [200, 200, 200, 255]);
|
||||
}
|
||||
|
||||
function showStats(client) {
|
||||
let data = playerData[client.index];
|
||||
if (data) {
|
||||
messageClient("=== YOUR STATISTICS ===", client, [255, 200, 100, 255]);
|
||||
messageClient("Kills: " + data.kills, client, [100, 255, 100, 255]);
|
||||
messageClient("Deaths: " + data.deaths, client, [255, 100, 100, 255]);
|
||||
let kd = data.deaths > 0 ? (data.kills / data.deaths).toFixed(2) : data.kills.toFixed(2);
|
||||
messageClient("K/D Ratio: " + kd, client, [200, 200, 255, 255]);
|
||||
}
|
||||
}
|
||||
|
||||
function showOnlinePlayers(client) {
|
||||
let clients = getClients();
|
||||
messageClient("=== ONLINE PLAYERS (" + clients.length + ") ===", client, [255, 200, 100, 255]);
|
||||
|
||||
for (let i = 0; i < clients.length; i++) {
|
||||
let c = clients[i];
|
||||
let data = playerData[c.index] || { kills: 0, deaths: 0 };
|
||||
messageClient(c.name + " - K: " + data.kills + " D: " + data.deaths, client, [200, 200, 200, 255]);
|
||||
}
|
||||
}
|
||||
|
||||
function getClientFromPed(ped) {
|
||||
let clients = getClients();
|
||||
for (let i = 0; i < clients.length; i++) {
|
||||
if (clients[i].player && clients[i].player == ped) {
|
||||
return clients[i];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
console.log("[Freeroam] Server script loaded!");
|
||||
5
resources/teleport/meta.xml
Normal file
5
resources/teleport/meta.xml
Normal file
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<meta>
|
||||
<info author="GTAConnected Server" type="script" version="1.0.0" description="Teleport system with Liberty City locations" />
|
||||
<script src="server.js" type="server" language="javascript" />
|
||||
</meta>
|
||||
314
resources/teleport/server.js
Normal file
314
resources/teleport/server.js
Normal file
@@ -0,0 +1,314 @@
|
||||
// ============================================================================
|
||||
// TELEPORT RESOURCE - Server Side
|
||||
// Teleportation system with Liberty City (GTA IV) locations
|
||||
// ============================================================================
|
||||
|
||||
// Liberty City Teleport Locations
|
||||
const locations = {
|
||||
// Algonquin (Manhattan)
|
||||
"starjunction": { x: -252.0, y: 947.0, z: 15.0, name: "Star Junction (Times Square)" },
|
||||
"middlepark": { x: -365.0, y: 1163.0, z: 14.0, name: "Middle Park" },
|
||||
"rotterdam": { x: 237.0, y: 1002.0, z: 18.0, name: "Rotterdam Tower" },
|
||||
"triangletower": { x: -336.0, y: 747.0, z: 28.0, name: "Triangle Tower" },
|
||||
"getaLife": { x: -268.0, y: 456.0, z: 14.0, name: "GetaLife Building" },
|
||||
"castle": { x: -411.0, y: 1503.0, z: 10.0, name: "Castle Garden City" },
|
||||
"exchange": { x: 98.0, y: -122.0, z: 14.0, name: "The Exchange" },
|
||||
"chinatown": { x: -141.0, y: 289.0, z: 14.0, name: "Chinatown" },
|
||||
"happiness": { x: -722.0, y: -17.0, z: 3.0, name: "Happiness Island" },
|
||||
"algonquin": { x: -252.0, y: 947.0, z: 15.0, name: "Algonquin" },
|
||||
|
||||
// Broker/Dukes (Brooklyn/Queens)
|
||||
"broker": { x: 932.0, y: -495.0, z: 15.0, name: "Broker Bridge" },
|
||||
"firefly": { x: 1366.0, y: -647.0, z: 35.0, name: "Firefly Projects" },
|
||||
"outlook": { x: 975.0, y: -251.0, z: 10.0, name: "Outlook Park" },
|
||||
"beach": { x: 1571.0, y: -377.0, z: 18.0, name: "Firefly Beach" },
|
||||
"hove": { x: 1017.0, y: -505.0, z: 19.0, name: "Hove Beach" },
|
||||
"meadows": { x: 1772.0, y: 507.0, z: 23.0, name: "Meadows Park" },
|
||||
"willis": { x: 1460.0, y: 349.0, z: 24.0, name: "Willis" },
|
||||
"airport": { x: 2140.0, y: 465.0, z: 6.0, name: "Francis International Airport" },
|
||||
|
||||
// Bohan (Bronx)
|
||||
"bohan": { x: 1243.0, y: -196.0, z: 26.0, name: "South Bohan" },
|
||||
"northholland": { x: -429.0, y: 1494.0, z: 11.0, name: "North Holland" },
|
||||
"industrial": { x: 773.0, y: 1872.0, z: 10.0, name: "Industrial" },
|
||||
|
||||
// Alderney (New Jersey)
|
||||
"alderney": { x: -1149.0, y: 380.0, z: 21.0, name: "Alderney City" },
|
||||
"alderneyport": { x: -1420.0, y: 741.0, z: 24.0, name: "Alderney Port" },
|
||||
"westdyke": { x: -1745.0, y: 1157.0, z: 25.0, name: "Westdyke" },
|
||||
"acter": { x: -1149.0, y: 380.0, z: 21.0, name: "Acter" },
|
||||
"berchem": { x: -1273.0, y: 1408.0, z: 22.0, name: "Berchem" },
|
||||
"tudor": { x: -1106.0, y: -69.0, z: 10.0, name: "Tudor" },
|
||||
"leftwood": { x: -1525.0, y: 979.0, z: 25.0, name: "Leftwood" },
|
||||
|
||||
// Points of Interest
|
||||
"hospital": { x: 984.0, y: -237.0, z: 10.0, name: "Broker Hospital" },
|
||||
"hospitalalg": { x: -471.0, y: 338.0, z: 8.0, name: "Algonquin Hospital" },
|
||||
"police": { x: -1227.0, y: 200.0, z: 19.0, name: "Alderney Police Station" },
|
||||
"policealgonquin": { x: -336.0, y: 747.0, z: 28.0, name: "Algonquin Police Station" },
|
||||
"bowling": { x: 1007.0, y: -515.0, z: 14.0, name: "Bowling Alley" },
|
||||
"cabaret": { x: -381.0, y: 524.0, z: 14.0, name: "Cabaret Club" },
|
||||
"swingerclub": { x: 1068.0, y: -429.0, z: 15.0, name: "Strip Club" },
|
||||
"burgershot": { x: -225.0, y: -201.0, z: 10.0, name: "Burger Shot" },
|
||||
"cluckinbell": { x: 907.0, y: -509.0, z: 15.0, name: "Cluckin' Bell" },
|
||||
|
||||
// Special locations
|
||||
"helipad": { x: -290.0, y: -400.0, z: 81.0, name: "Helicopter Pad" },
|
||||
"tower": { x: 237.0, y: 1002.0, z: 200.0, name: "Tower Top" },
|
||||
"bridge1": { x: 500.0, y: -80.0, z: 60.0, name: "Algonquin Bridge" },
|
||||
"bridge2": { x: 800.0, y: 600.0, z: 60.0, name: "East Borough Bridge" }
|
||||
};
|
||||
|
||||
// Custom player waypoints
|
||||
let playerWaypoints = {};
|
||||
|
||||
// ============================================================================
|
||||
// EVENTS
|
||||
// ============================================================================
|
||||
|
||||
addEventHandler("OnResourceStart", function(event, resource) {
|
||||
console.log("[Teleport] Resource started - " + Object.keys(locations).length + " locations available");
|
||||
});
|
||||
|
||||
addEventHandler("OnPlayerCommand", function(event, client, command, params) {
|
||||
let cmd = command.toLowerCase();
|
||||
|
||||
switch(cmd) {
|
||||
case "tp":
|
||||
case "teleport":
|
||||
case "goto":
|
||||
if (params && params.length > 0) {
|
||||
let locationName = params.toLowerCase().split(" ")[0];
|
||||
teleportToLocation(client, locationName);
|
||||
} else {
|
||||
messageClient("[USAGE] /tp <location>", client, [255, 200, 100, 255]);
|
||||
messageClient("[TIP] Use /tplist to see available locations", client, [200, 200, 200, 255]);
|
||||
}
|
||||
break;
|
||||
|
||||
case "tplist":
|
||||
case "locations":
|
||||
showLocationList(client);
|
||||
break;
|
||||
|
||||
case "tpsearch":
|
||||
case "findlocation":
|
||||
if (params && params.length > 0) {
|
||||
searchLocations(client, params.toLowerCase());
|
||||
} else {
|
||||
messageClient("[USAGE] /tpsearch <partial_name>", client, [255, 200, 100, 255]);
|
||||
}
|
||||
break;
|
||||
|
||||
case "setpos":
|
||||
case "tpcoords":
|
||||
if (params && params.length > 0) {
|
||||
let coords = params.split(" ");
|
||||
if (coords.length >= 3) {
|
||||
let x = parseFloat(coords[0]);
|
||||
let y = parseFloat(coords[1]);
|
||||
let z = parseFloat(coords[2]);
|
||||
|
||||
if (!isNaN(x) && !isNaN(y) && !isNaN(z)) {
|
||||
teleportToCoords(client, x, y, z);
|
||||
} else {
|
||||
messageClient("[TELEPORT] Invalid coordinates!", client, [255, 100, 100, 255]);
|
||||
}
|
||||
} else {
|
||||
messageClient("[USAGE] /setpos <x> <y> <z>", client, [255, 200, 100, 255]);
|
||||
}
|
||||
} else {
|
||||
messageClient("[USAGE] /setpos <x> <y> <z>", client, [255, 200, 100, 255]);
|
||||
}
|
||||
break;
|
||||
|
||||
case "savewaypoint":
|
||||
case "setwp":
|
||||
if (params && params.length > 0) {
|
||||
saveWaypoint(client, params.toLowerCase());
|
||||
} else {
|
||||
messageClient("[USAGE] /savewaypoint <name>", client, [255, 200, 100, 255]);
|
||||
}
|
||||
break;
|
||||
|
||||
case "delwaypoint":
|
||||
case "deletewp":
|
||||
if (params && params.length > 0) {
|
||||
deleteWaypoint(client, params.toLowerCase());
|
||||
} else {
|
||||
messageClient("[USAGE] /delwaypoint <name>", client, [255, 200, 100, 255]);
|
||||
}
|
||||
break;
|
||||
|
||||
case "waypoints":
|
||||
case "mywaypoints":
|
||||
showWaypoints(client);
|
||||
break;
|
||||
|
||||
case "tpwp":
|
||||
case "gotowp":
|
||||
if (params && params.length > 0) {
|
||||
teleportToWaypoint(client, params.toLowerCase());
|
||||
} else {
|
||||
messageClient("[USAGE] /tpwp <waypoint_name>", client, [255, 200, 100, 255]);
|
||||
}
|
||||
break;
|
||||
|
||||
// Quick teleport commands
|
||||
case "airport":
|
||||
teleportToLocation(client, "airport");
|
||||
break;
|
||||
|
||||
case "hospital":
|
||||
teleportToLocation(client, "hospital");
|
||||
break;
|
||||
|
||||
case "beach":
|
||||
teleportToLocation(client, "beach");
|
||||
break;
|
||||
|
||||
case "park":
|
||||
teleportToLocation(client, "middlepark");
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
// ============================================================================
|
||||
// FUNCTIONS
|
||||
// ============================================================================
|
||||
|
||||
function teleportToLocation(client, locationName) {
|
||||
// Check server locations
|
||||
if (locations[locationName]) {
|
||||
let loc = locations[locationName];
|
||||
teleportPlayer(client, loc.x, loc.y, loc.z);
|
||||
messageClient("[TELEPORT] Teleported to: " + loc.name, client, [100, 255, 100, 255]);
|
||||
console.log("[Teleport] " + client.name + " teleported to " + loc.name);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check player waypoints
|
||||
if (playerWaypoints[client.index] && playerWaypoints[client.index][locationName]) {
|
||||
let wp = playerWaypoints[client.index][locationName];
|
||||
teleportPlayer(client, wp.x, wp.y, wp.z);
|
||||
messageClient("[TELEPORT] Teleported to waypoint: " + locationName, client, [100, 255, 100, 255]);
|
||||
return;
|
||||
}
|
||||
|
||||
messageClient("[TELEPORT] Location '" + locationName + "' not found!", client, [255, 100, 100, 255]);
|
||||
messageClient("[TIP] Use /tplist or /tpsearch <name>", client, [200, 200, 200, 255]);
|
||||
}
|
||||
|
||||
function teleportToCoords(client, x, y, z) {
|
||||
teleportPlayer(client, x, y, z);
|
||||
messageClient("[TELEPORT] Teleported to: X:" + x.toFixed(1) + " Y:" + y.toFixed(1) + " Z:" + z.toFixed(1), client, [100, 255, 100, 255]);
|
||||
}
|
||||
|
||||
function teleportPlayer(client, x, y, z) {
|
||||
if (client.player) {
|
||||
// If in vehicle, teleport vehicle
|
||||
if (client.player.vehicle) {
|
||||
client.player.vehicle.position = [x, y, z];
|
||||
} else {
|
||||
client.player.position = [x, y, z];
|
||||
}
|
||||
} else {
|
||||
messageClient("[TELEPORT] You need to spawn first!", client, [255, 100, 100, 255]);
|
||||
}
|
||||
}
|
||||
|
||||
function showLocationList(client) {
|
||||
messageClient("=== TELEPORT LOCATIONS ===", client, [255, 200, 100, 255]);
|
||||
messageClient("-- Algonquin --", client, [100, 200, 255, 255]);
|
||||
messageClient("starjunction, middlepark, rotterdam, chinatown, exchange, happiness", client, [200, 200, 200, 255]);
|
||||
|
||||
messageClient("-- Broker/Dukes --", client, [100, 200, 255, 255]);
|
||||
messageClient("broker, firefly, outlook, beach, hove, meadows, willis, airport", client, [200, 200, 200, 255]);
|
||||
|
||||
messageClient("-- Bohan --", client, [100, 200, 255, 255]);
|
||||
messageClient("bohan, northholland, industrial", client, [200, 200, 200, 255]);
|
||||
|
||||
messageClient("-- Alderney --", client, [100, 200, 255, 255]);
|
||||
messageClient("alderney, alderneyport, westdyke, acter, berchem, tudor, leftwood", client, [200, 200, 200, 255]);
|
||||
|
||||
messageClient("-- Points of Interest --", client, [100, 200, 255, 255]);
|
||||
messageClient("hospital, hospitalalg, police, bowling, cabaret, burgershot, helipad", client, [200, 200, 200, 255]);
|
||||
|
||||
messageClient("[TIP] Use /tpsearch <name> to find specific locations", client, [255, 200, 100, 255]);
|
||||
}
|
||||
|
||||
function searchLocations(client, searchTerm) {
|
||||
let found = [];
|
||||
for (let name in locations) {
|
||||
if (name.indexOf(searchTerm) !== -1 ||
|
||||
locations[name].name.toLowerCase().indexOf(searchTerm) !== -1) {
|
||||
found.push(name + " (" + locations[name].name + ")");
|
||||
}
|
||||
}
|
||||
|
||||
if (found.length > 0) {
|
||||
messageClient("=== LOCATIONS MATCHING '" + searchTerm.toUpperCase() + "' ===", client, [255, 200, 100, 255]);
|
||||
for (let i = 0; i < found.length; i++) {
|
||||
messageClient(found[i], client, [200, 200, 200, 255]);
|
||||
}
|
||||
} else {
|
||||
messageClient("[TELEPORT] No locations found matching '" + searchTerm + "'", client, [255, 100, 100, 255]);
|
||||
}
|
||||
}
|
||||
|
||||
function saveWaypoint(client, waypointName) {
|
||||
if (!client.player) {
|
||||
messageClient("[WAYPOINT] You need to spawn first!", client, [255, 100, 100, 255]);
|
||||
return;
|
||||
}
|
||||
|
||||
let pos = client.player.position;
|
||||
|
||||
if (!playerWaypoints[client.index]) {
|
||||
playerWaypoints[client.index] = {};
|
||||
}
|
||||
|
||||
playerWaypoints[client.index][waypointName] = {
|
||||
x: pos[0],
|
||||
y: pos[1],
|
||||
z: pos[2]
|
||||
};
|
||||
|
||||
messageClient("[WAYPOINT] Saved waypoint: " + waypointName, client, [100, 255, 100, 255]);
|
||||
messageClient("[WAYPOINT] Use /tpwp " + waypointName + " to teleport here", client, [200, 200, 200, 255]);
|
||||
}
|
||||
|
||||
function deleteWaypoint(client, waypointName) {
|
||||
if (playerWaypoints[client.index] && playerWaypoints[client.index][waypointName]) {
|
||||
delete playerWaypoints[client.index][waypointName];
|
||||
messageClient("[WAYPOINT] Deleted waypoint: " + waypointName, client, [100, 255, 100, 255]);
|
||||
} else {
|
||||
messageClient("[WAYPOINT] Waypoint not found: " + waypointName, client, [255, 100, 100, 255]);
|
||||
}
|
||||
}
|
||||
|
||||
function showWaypoints(client) {
|
||||
if (!playerWaypoints[client.index] || Object.keys(playerWaypoints[client.index]).length === 0) {
|
||||
messageClient("[WAYPOINT] You have no saved waypoints", client, [255, 200, 100, 255]);
|
||||
messageClient("[TIP] Use /savewaypoint <name> to save your current position", client, [200, 200, 200, 255]);
|
||||
return;
|
||||
}
|
||||
|
||||
messageClient("=== YOUR WAYPOINTS ===", client, [255, 200, 100, 255]);
|
||||
for (let name in playerWaypoints[client.index]) {
|
||||
let wp = playerWaypoints[client.index][name];
|
||||
messageClient(name + " - X:" + wp.x.toFixed(1) + " Y:" + wp.y.toFixed(1) + " Z:" + wp.z.toFixed(1), client, [200, 200, 200, 255]);
|
||||
}
|
||||
}
|
||||
|
||||
function teleportToWaypoint(client, waypointName) {
|
||||
if (playerWaypoints[client.index] && playerWaypoints[client.index][waypointName]) {
|
||||
let wp = playerWaypoints[client.index][waypointName];
|
||||
teleportPlayer(client, wp.x, wp.y, wp.z);
|
||||
messageClient("[WAYPOINT] Teleported to: " + waypointName, client, [100, 255, 100, 255]);
|
||||
} else {
|
||||
messageClient("[WAYPOINT] Waypoint not found: " + waypointName, client, [255, 100, 100, 255]);
|
||||
}
|
||||
}
|
||||
|
||||
console.log("[Teleport] Server script loaded!");
|
||||
5
resources/vehicles/meta.xml
Normal file
5
resources/vehicles/meta.xml
Normal file
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<meta>
|
||||
<info author="GTAConnected Server" type="script" version="1.0.0" description="Vehicle spawning and management system" />
|
||||
<script src="server.js" type="server" language="javascript" />
|
||||
</meta>
|
||||
347
resources/vehicles/server.js
Normal file
347
resources/vehicles/server.js
Normal file
@@ -0,0 +1,347 @@
|
||||
// ============================================================================
|
||||
// VEHICLES RESOURCE - Server Side
|
||||
// Handles vehicle spawning and management for GTA IV
|
||||
// ============================================================================
|
||||
|
||||
// GTA IV Vehicle Database - Model names and their hash IDs
|
||||
const vehicles = {
|
||||
// Sports Cars
|
||||
"infernus": -1461482751,
|
||||
"turismo": -982130927,
|
||||
"comet": 1063483177,
|
||||
"banshee": -1823484407,
|
||||
"sultan": 970598228,
|
||||
"sultanrs": 970598228,
|
||||
"coquette": 108773431,
|
||||
"feltzer": -349601129,
|
||||
"f620": -591651781,
|
||||
"buffalo": -304802106,
|
||||
|
||||
// Muscle Cars
|
||||
"sabregt": 1357660823,
|
||||
"stalion": 1923400478,
|
||||
"vigero": -825837129,
|
||||
"dukes": 723973206,
|
||||
"ruiner": -227741703,
|
||||
"phoenix": -2095439403,
|
||||
"gauntlet": -1800170043,
|
||||
"dominator": 80636076,
|
||||
|
||||
// Super Cars
|
||||
"entityxf": -1291952903,
|
||||
"adder": -1216765807,
|
||||
"vacca": 338562499,
|
||||
"bullet": -1696146015,
|
||||
"cheetah": -1311154784,
|
||||
|
||||
// SUVs & 4x4
|
||||
"patriot": -808457413,
|
||||
"cavalcade": 2006918058,
|
||||
"granger": 1269098716,
|
||||
"huntley": 486987393,
|
||||
"landstalker": 1269098716,
|
||||
"rebla": 83136452,
|
||||
"habanero": 884422927,
|
||||
"rocoto": 2136773105,
|
||||
"serrano": 1337041428,
|
||||
|
||||
// Sedans
|
||||
"oracle": 1348744438,
|
||||
"schafter": -888242983,
|
||||
"admiral": -1645064850,
|
||||
"vincent": -884237051,
|
||||
"presidente": -1150599089,
|
||||
"cognoscenti": -2030171296,
|
||||
"intruder": 886934177,
|
||||
"merit": -1355452010,
|
||||
"premier": -1883869285,
|
||||
"primo": -1150599089,
|
||||
"stratum": 1723137093,
|
||||
"sultan": 970598228,
|
||||
|
||||
// Compacts
|
||||
"blista": -344943009,
|
||||
"dilettante": -1130810103,
|
||||
"issi": 1854776567,
|
||||
"panto": -431692672,
|
||||
"rhapsody": 841808271,
|
||||
|
||||
// Coupes
|
||||
"sentinel": 1349725314,
|
||||
"sentinelxs": 873639469,
|
||||
"zion": -1122289213,
|
||||
|
||||
// Vans
|
||||
"burrito": -1346687836,
|
||||
"minivan": -310465116,
|
||||
"moonbeam": 525509695,
|
||||
"rumpo": 1162065741,
|
||||
"speedo": -810318068,
|
||||
"youga": 65402552,
|
||||
"pony": -119658072,
|
||||
|
||||
// Trucks
|
||||
"benson": 2053223216,
|
||||
"mule": 904750859,
|
||||
"pounder": 2112052861,
|
||||
"phantom": -2137348917,
|
||||
"hauler": 1518533038,
|
||||
"flatbed": 1353720154,
|
||||
"biff": 850991848,
|
||||
|
||||
// Emergency
|
||||
"police": 2046537925,
|
||||
"police2": -1627000575,
|
||||
"police3": 1912215274,
|
||||
"policew": 1912215274,
|
||||
"polpatriot": 1912215274,
|
||||
"fbi": 1127131465,
|
||||
"fbi2": -1647941228,
|
||||
"noose": -1683328900,
|
||||
"enforcer": 2046537925,
|
||||
"ambulance": 1171614426,
|
||||
"firetruk": 1938952078,
|
||||
|
||||
// Motorcycles
|
||||
"nrg900": -1706076364,
|
||||
"pcj600": -909201658,
|
||||
"sanchez": 788045382,
|
||||
"faggio": 55628203,
|
||||
"bati": -891462355,
|
||||
"akuma": 1672195559,
|
||||
"double": -1670998136,
|
||||
"hakuchou": 1265391242,
|
||||
"hexer": 301427732,
|
||||
"innovation": -2020483426,
|
||||
"lectro": 640818791,
|
||||
"nemesis": -634879114,
|
||||
"daemon": 2006142190,
|
||||
"zombiea": -1009268949,
|
||||
|
||||
// Boats
|
||||
"jetmax": 861409633,
|
||||
"marquis": -1043459709,
|
||||
"predator": -488123221,
|
||||
"reefer": 1016996501,
|
||||
"squalo": 400514754,
|
||||
"suntrap": -282946103,
|
||||
"tropic": 290013743,
|
||||
"dinghy": 1033245328,
|
||||
|
||||
// Helicopters
|
||||
"annihilator": 837858166,
|
||||
"maverick": -1660661558,
|
||||
"polmav": 353883353,
|
||||
"buzzard": 788747387,
|
||||
|
||||
// Planes
|
||||
"shamal": -1214293858,
|
||||
|
||||
// Misc
|
||||
"taxi": -956048545,
|
||||
"cabby": -1767210897,
|
||||
"stretch": -1961627517,
|
||||
"bus": -713569950,
|
||||
"trashmaster": 1917016601,
|
||||
"forklift": 1491375716,
|
||||
"caddy": 1147287684,
|
||||
"airtug": 1560980623,
|
||||
"ripley": -845961253,
|
||||
"bulldozer": 1886712733,
|
||||
};
|
||||
|
||||
// Store spawned vehicles per player
|
||||
let playerVehicles = {};
|
||||
|
||||
// ============================================================================
|
||||
// EVENTS
|
||||
// ============================================================================
|
||||
|
||||
addEventHandler("OnResourceStart", function(event, resource) {
|
||||
console.log("[Vehicles] Resource started - " + Object.keys(vehicles).length + " vehicles available");
|
||||
});
|
||||
|
||||
addEventHandler("OnPlayerQuit", function(event, client, reason) {
|
||||
// Clean up player's vehicles
|
||||
deletePlayerVehicles(client);
|
||||
});
|
||||
|
||||
addEventHandler("OnPlayerCommand", function(event, client, command, params) {
|
||||
let cmd = command.toLowerCase();
|
||||
|
||||
switch(cmd) {
|
||||
case "v":
|
||||
case "veh":
|
||||
case "car":
|
||||
case "vehicle":
|
||||
if (params && params.length > 0) {
|
||||
let vehicleName = params.toLowerCase().split(" ")[0];
|
||||
spawnVehicleForPlayer(client, vehicleName);
|
||||
} else {
|
||||
messageClient("[USAGE] /v <vehicle_name>", client, [255, 200, 100, 255]);
|
||||
messageClient("[TIP] Use /vlist to see available vehicles", client, [200, 200, 200, 255]);
|
||||
}
|
||||
break;
|
||||
|
||||
case "dv":
|
||||
case "deletevehicle":
|
||||
case "destroyvehicle":
|
||||
deletePlayerVehicles(client);
|
||||
messageClient("[VEHICLES] Your vehicles have been deleted!", client, [100, 255, 100, 255]);
|
||||
break;
|
||||
|
||||
case "vlist":
|
||||
case "vehicles":
|
||||
case "carlist":
|
||||
showVehicleList(client);
|
||||
break;
|
||||
|
||||
case "vsearch":
|
||||
case "findvehicle":
|
||||
if (params && params.length > 0) {
|
||||
searchVehicles(client, params.toLowerCase());
|
||||
} else {
|
||||
messageClient("[USAGE] /vsearch <partial_name>", client, [255, 200, 100, 255]);
|
||||
}
|
||||
break;
|
||||
|
||||
case "vcolor":
|
||||
case "carcolor":
|
||||
if (params && params.length > 0) {
|
||||
let colors = params.split(" ");
|
||||
if (colors.length >= 2) {
|
||||
setVehicleColor(client, parseInt(colors[0]), parseInt(colors[1]));
|
||||
} else {
|
||||
messageClient("[USAGE] /vcolor <color1> <color2>", client, [255, 200, 100, 255]);
|
||||
messageClient("[TIP] Colors are 0-131 for GTA IV", client, [200, 200, 200, 255]);
|
||||
}
|
||||
} else {
|
||||
messageClient("[USAGE] /vcolor <color1> <color2>", client, [255, 200, 100, 255]);
|
||||
}
|
||||
break;
|
||||
|
||||
case "nitro":
|
||||
case "nos":
|
||||
if (client.player && client.player.vehicle) {
|
||||
// Simulate nitro boost by increasing vehicle speed
|
||||
let veh = client.player.vehicle;
|
||||
messageClient("[VEHICLES] NITRO! Vehicle boosted!", client, [255, 100, 255, 255]);
|
||||
} else {
|
||||
messageClient("[VEHICLES] You need to be in a vehicle!", client, [255, 100, 100, 255]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
// ============================================================================
|
||||
// FUNCTIONS
|
||||
// ============================================================================
|
||||
|
||||
function spawnVehicleForPlayer(client, vehicleName) {
|
||||
// Check if vehicle exists
|
||||
if (!vehicles[vehicleName]) {
|
||||
messageClient("[VEHICLES] Vehicle '" + vehicleName + "' not found!", client, [255, 100, 100, 255]);
|
||||
messageClient("[TIP] Use /vlist or /vsearch <name> to find vehicles", client, [200, 200, 200, 255]);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!client.player) {
|
||||
messageClient("[VEHICLES] You need to spawn first!", client, [255, 100, 100, 255]);
|
||||
return;
|
||||
}
|
||||
|
||||
// Delete previous vehicles
|
||||
deletePlayerVehicles(client);
|
||||
|
||||
// Get player position and heading
|
||||
let pos = client.player.position;
|
||||
let heading = client.player.heading;
|
||||
|
||||
// Spawn slightly in front of player
|
||||
let spawnX = pos[0] + (Math.sin(heading) * 3);
|
||||
let spawnY = pos[1] + (Math.cos(heading) * 3);
|
||||
let spawnZ = pos[2] + 1;
|
||||
|
||||
// Create the vehicle
|
||||
let modelHash = vehicles[vehicleName];
|
||||
let vehicle = gta.createVehicle(modelHash, [spawnX, spawnY, spawnZ], heading);
|
||||
|
||||
if (vehicle) {
|
||||
// Store vehicle for this player
|
||||
if (!playerVehicles[client.index]) {
|
||||
playerVehicles[client.index] = [];
|
||||
}
|
||||
playerVehicles[client.index].push(vehicle);
|
||||
|
||||
// Set vehicle properties
|
||||
vehicle.health = 1000;
|
||||
vehicle.locked = false;
|
||||
vehicle.engine = true;
|
||||
|
||||
// Random colors
|
||||
let color1 = Math.floor(Math.random() * 132);
|
||||
let color2 = Math.floor(Math.random() * 132);
|
||||
vehicle.colour1 = color1;
|
||||
vehicle.colour2 = color2;
|
||||
|
||||
messageClient("[VEHICLES] Spawned: " + vehicleName.toUpperCase(), client, [100, 255, 100, 255]);
|
||||
console.log("[Vehicles] " + client.name + " spawned " + vehicleName);
|
||||
} else {
|
||||
messageClient("[VEHICLES] Failed to spawn vehicle!", client, [255, 100, 100, 255]);
|
||||
}
|
||||
}
|
||||
|
||||
function deletePlayerVehicles(client) {
|
||||
if (playerVehicles[client.index]) {
|
||||
for (let i = 0; i < playerVehicles[client.index].length; i++) {
|
||||
let veh = playerVehicles[client.index][i];
|
||||
if (veh) {
|
||||
destroyElement(veh);
|
||||
}
|
||||
}
|
||||
playerVehicles[client.index] = [];
|
||||
}
|
||||
}
|
||||
|
||||
function showVehicleList(client) {
|
||||
messageClient("=== VEHICLE CATEGORIES ===", client, [255, 200, 100, 255]);
|
||||
messageClient("Sports: infernus, turismo, comet, banshee, sultan, coquette, feltzer", client, [200, 200, 200, 255]);
|
||||
messageClient("Muscle: sabregt, stalion, vigero, dukes, ruiner, phoenix", client, [200, 200, 200, 255]);
|
||||
messageClient("Super: entityxf, adder, vacca, bullet, cheetah", client, [200, 200, 200, 255]);
|
||||
messageClient("SUV: patriot, cavalcade, granger, huntley, landstalker", client, [200, 200, 200, 255]);
|
||||
messageClient("Sedan: oracle, schafter, admiral, vincent, presidente", client, [200, 200, 200, 255]);
|
||||
messageClient("Emergency: police, fbi, noose, ambulance, firetruk", client, [200, 200, 200, 255]);
|
||||
messageClient("Bikes: nrg900, pcj600, sanchez, faggio, bati, akuma", client, [200, 200, 200, 255]);
|
||||
messageClient("Air: annihilator, maverick, polmav, buzzard, shamal", client, [200, 200, 200, 255]);
|
||||
messageClient("Boats: jetmax, marquis, predator, tropic, dinghy", client, [200, 200, 200, 255]);
|
||||
messageClient("[TIP] Use /vsearch <name> to search for specific vehicles", client, [255, 200, 100, 255]);
|
||||
}
|
||||
|
||||
function searchVehicles(client, searchTerm) {
|
||||
let found = [];
|
||||
for (let name in vehicles) {
|
||||
if (name.indexOf(searchTerm) !== -1) {
|
||||
found.push(name);
|
||||
}
|
||||
}
|
||||
|
||||
if (found.length > 0) {
|
||||
messageClient("=== VEHICLES MATCHING '" + searchTerm.toUpperCase() + "' ===", client, [255, 200, 100, 255]);
|
||||
messageClient(found.join(", "), client, [200, 200, 200, 255]);
|
||||
} else {
|
||||
messageClient("[VEHICLES] No vehicles found matching '" + searchTerm + "'", client, [255, 100, 100, 255]);
|
||||
}
|
||||
}
|
||||
|
||||
function setVehicleColor(client, color1, color2) {
|
||||
if (client.player && client.player.vehicle) {
|
||||
let veh = client.player.vehicle;
|
||||
veh.colour1 = color1;
|
||||
veh.colour2 = color2;
|
||||
messageClient("[VEHICLES] Vehicle color changed to: " + color1 + ", " + color2, client, [100, 255, 100, 255]);
|
||||
} else {
|
||||
messageClient("[VEHICLES] You need to be in a vehicle!", client, [255, 100, 100, 255]);
|
||||
}
|
||||
}
|
||||
|
||||
console.log("[Vehicles] Server script loaded!");
|
||||
5
resources/world/meta.xml
Normal file
5
resources/world/meta.xml
Normal file
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<meta>
|
||||
<info author="GTAConnected Server" type="script" version="1.0.0" description="World control - weather, time, and environment" />
|
||||
<script src="server.js" type="server" language="javascript" />
|
||||
</meta>
|
||||
240
resources/world/server.js
Normal file
240
resources/world/server.js
Normal file
@@ -0,0 +1,240 @@
|
||||
// ============================================================================
|
||||
// WORLD RESOURCE - Server Side
|
||||
// Handles weather, time, and world environment controls
|
||||
// ============================================================================
|
||||
|
||||
// GTA IV Weather Types
|
||||
const weatherTypes = {
|
||||
0: "Extra Sunny",
|
||||
1: "Sunny",
|
||||
2: "Sunny Windy",
|
||||
3: "Cloudy",
|
||||
4: "Raining",
|
||||
5: "Drizzle",
|
||||
6: "Foggy",
|
||||
7: "Thunder",
|
||||
8: "Extra Sunny 2",
|
||||
9: "Sunny Windy 2"
|
||||
};
|
||||
|
||||
// World state
|
||||
let worldState = {
|
||||
weather: 1,
|
||||
hour: 12,
|
||||
minute: 0,
|
||||
timeFrozen: false,
|
||||
weatherLocked: false
|
||||
};
|
||||
|
||||
// Time sync interval
|
||||
let timeInterval = null;
|
||||
|
||||
// ============================================================================
|
||||
// EVENTS
|
||||
// ============================================================================
|
||||
|
||||
addEventHandler("OnResourceStart", function(event, resource) {
|
||||
console.log("[World] Resource started");
|
||||
|
||||
// Start time synchronization (advances time every real second = 1 game minute)
|
||||
timeInterval = setInterval(function() {
|
||||
if (!worldState.timeFrozen) {
|
||||
advanceTime();
|
||||
}
|
||||
}, 1000); // 1 second = 1 game minute
|
||||
|
||||
console.log("[World] Time synchronization started");
|
||||
});
|
||||
|
||||
addEventHandler("OnResourceStop", function(event, resource) {
|
||||
if (timeInterval) {
|
||||
clearInterval(timeInterval);
|
||||
}
|
||||
console.log("[World] Resource stopped");
|
||||
});
|
||||
|
||||
addEventHandler("OnPlayerJoined", function(event, client) {
|
||||
// Sync world state to new player
|
||||
syncWorldToClient(client);
|
||||
});
|
||||
|
||||
addEventHandler("OnPlayerCommand", function(event, client, command, params) {
|
||||
let cmd = command.toLowerCase();
|
||||
|
||||
switch(cmd) {
|
||||
case "weather":
|
||||
case "setweather":
|
||||
if (params && params.length > 0) {
|
||||
let weatherId = parseInt(params);
|
||||
if (!isNaN(weatherId) && weatherId >= 0 && weatherId <= 9) {
|
||||
setWeather(weatherId);
|
||||
message("[WORLD] Weather changed to: " + weatherTypes[weatherId], [100, 200, 255, 255]);
|
||||
} else {
|
||||
messageClient("[WORLD] Invalid weather ID (0-9)", client, [255, 100, 100, 255]);
|
||||
}
|
||||
} else {
|
||||
messageClient("[USAGE] /weather <0-9>", client, [255, 200, 100, 255]);
|
||||
showWeatherList(client);
|
||||
}
|
||||
break;
|
||||
|
||||
case "time":
|
||||
case "settime":
|
||||
if (params && params.length > 0) {
|
||||
let parts = params.split(":");
|
||||
let hour = parseInt(parts[0]);
|
||||
let minute = parts.length > 1 ? parseInt(parts[1]) : 0;
|
||||
|
||||
if (!isNaN(hour) && hour >= 0 && hour <= 23) {
|
||||
setTime(hour, minute);
|
||||
message("[WORLD] Time changed to: " + formatTime(hour, minute), [100, 200, 255, 255]);
|
||||
} else {
|
||||
messageClient("[WORLD] Invalid time (0-23 hours)", client, [255, 100, 100, 255]);
|
||||
}
|
||||
} else {
|
||||
messageClient("[USAGE] /time <hour> or /time <hour:minute>", client, [255, 200, 100, 255]);
|
||||
}
|
||||
break;
|
||||
|
||||
case "morning":
|
||||
setTime(8, 0);
|
||||
message("[WORLD] Time set to morning (8:00)", [100, 200, 255, 255]);
|
||||
break;
|
||||
|
||||
case "noon":
|
||||
case "midday":
|
||||
setTime(12, 0);
|
||||
message("[WORLD] Time set to noon (12:00)", [100, 200, 255, 255]);
|
||||
break;
|
||||
|
||||
case "evening":
|
||||
setTime(18, 0);
|
||||
message("[WORLD] Time set to evening (18:00)", [100, 200, 255, 255]);
|
||||
break;
|
||||
|
||||
case "night":
|
||||
case "midnight":
|
||||
setTime(0, 0);
|
||||
message("[WORLD] Time set to midnight (0:00)", [100, 200, 255, 255]);
|
||||
break;
|
||||
|
||||
case "sunny":
|
||||
setWeather(1);
|
||||
message("[WORLD] Weather set to Sunny", [100, 200, 255, 255]);
|
||||
break;
|
||||
|
||||
case "cloudy":
|
||||
setWeather(3);
|
||||
message("[WORLD] Weather set to Cloudy", [100, 200, 255, 255]);
|
||||
break;
|
||||
|
||||
case "rain":
|
||||
case "rainy":
|
||||
setWeather(4);
|
||||
message("[WORLD] Weather set to Raining", [100, 200, 255, 255]);
|
||||
break;
|
||||
|
||||
case "thunder":
|
||||
case "storm":
|
||||
setWeather(7);
|
||||
message("[WORLD] Weather set to Thunder", [100, 200, 255, 255]);
|
||||
break;
|
||||
|
||||
case "foggy":
|
||||
case "fog":
|
||||
setWeather(6);
|
||||
message("[WORLD] Weather set to Foggy", [100, 200, 255, 255]);
|
||||
break;
|
||||
|
||||
case "freezetime":
|
||||
case "stoptime":
|
||||
worldState.timeFrozen = !worldState.timeFrozen;
|
||||
let status = worldState.timeFrozen ? "frozen" : "unfrozen";
|
||||
message("[WORLD] Time has been " + status, [100, 200, 255, 255]);
|
||||
break;
|
||||
|
||||
case "gettime":
|
||||
messageClient("[WORLD] Current time: " + formatTime(worldState.hour, worldState.minute), client, [100, 200, 255, 255]);
|
||||
break;
|
||||
|
||||
case "getweather":
|
||||
messageClient("[WORLD] Current weather: " + weatherTypes[worldState.weather] + " (" + worldState.weather + ")", client, [100, 200, 255, 255]);
|
||||
break;
|
||||
|
||||
case "weatherlist":
|
||||
case "weathers":
|
||||
showWeatherList(client);
|
||||
break;
|
||||
|
||||
case "randomweather":
|
||||
let randomWeather = Math.floor(Math.random() * 10);
|
||||
setWeather(randomWeather);
|
||||
message("[WORLD] Random weather: " + weatherTypes[randomWeather], [100, 200, 255, 255]);
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
// ============================================================================
|
||||
// FUNCTIONS
|
||||
// ============================================================================
|
||||
|
||||
function setWeather(weatherId) {
|
||||
worldState.weather = weatherId;
|
||||
gta.weather = weatherId;
|
||||
console.log("[World] Weather changed to: " + weatherTypes[weatherId]);
|
||||
}
|
||||
|
||||
function setTime(hour, minute) {
|
||||
worldState.hour = hour;
|
||||
worldState.minute = minute || 0;
|
||||
gta.time = [hour, worldState.minute];
|
||||
console.log("[World] Time changed to: " + formatTime(hour, worldState.minute));
|
||||
}
|
||||
|
||||
function advanceTime() {
|
||||
worldState.minute++;
|
||||
if (worldState.minute >= 60) {
|
||||
worldState.minute = 0;
|
||||
worldState.hour++;
|
||||
if (worldState.hour >= 24) {
|
||||
worldState.hour = 0;
|
||||
}
|
||||
}
|
||||
gta.time = [worldState.hour, worldState.minute];
|
||||
}
|
||||
|
||||
function syncWorldToClient(client) {
|
||||
// Client will receive the global gta.time and gta.weather
|
||||
console.log("[World] Synced world state to " + client.name);
|
||||
}
|
||||
|
||||
function formatTime(hour, minute) {
|
||||
let h = hour.toString().padStart(2, "0");
|
||||
let m = minute.toString().padStart(2, "0");
|
||||
return h + ":" + m;
|
||||
}
|
||||
|
||||
function showWeatherList(client) {
|
||||
messageClient("=== WEATHER TYPES ===", client, [255, 200, 100, 255]);
|
||||
for (let id in weatherTypes) {
|
||||
messageClient(id + " - " + weatherTypes[id], client, [200, 200, 200, 255]);
|
||||
}
|
||||
}
|
||||
|
||||
// Polyfill for padStart if not available
|
||||
if (!String.prototype.padStart) {
|
||||
String.prototype.padStart = function(targetLength, padString) {
|
||||
targetLength = targetLength >> 0;
|
||||
padString = String(padString || ' ');
|
||||
if (this.length >= targetLength) {
|
||||
return String(this);
|
||||
}
|
||||
targetLength = targetLength - this.length;
|
||||
if (targetLength > padString.length) {
|
||||
padString += padString.repeat(targetLength / padString.length);
|
||||
}
|
||||
return padString.slice(0, targetLength) + String(this);
|
||||
};
|
||||
}
|
||||
|
||||
console.log("[World] Server script loaded!");
|
||||
37
server.xml
Normal file
37
server.xml
Normal file
@@ -0,0 +1,37 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<server>
|
||||
<!-- Server Information -->
|
||||
<servername>Liberty City Freeroam</servername>
|
||||
<maxplayers>32</maxplayers>
|
||||
<password></password>
|
||||
|
||||
<!-- Network Settings -->
|
||||
<port>22000</port>
|
||||
<httpport>22001</httpport>
|
||||
<announceserver>1</announceserver>
|
||||
|
||||
<!-- Game Settings -->
|
||||
<game>IV</game>
|
||||
<weather>1</weather>
|
||||
<time hour="12" minute="0"/>
|
||||
<trafficdensity>100</trafficdensity>
|
||||
<civiliandensity>100</civiliandensity>
|
||||
|
||||
<!-- Security Settings -->
|
||||
<anticheat>1</anticheat>
|
||||
<logfile>server.log</logfile>
|
||||
|
||||
<!-- Admin Settings -->
|
||||
<owner>Server Owner</owner>
|
||||
<website>https://gtaconnected.com</website>
|
||||
|
||||
<!-- Resources to Load -->
|
||||
<resources>
|
||||
<resource src="freeroam" />
|
||||
<resource src="admin" />
|
||||
<resource src="world" />
|
||||
<resource src="chat" />
|
||||
<resource src="teleport" />
|
||||
<resource src="vehicles" />
|
||||
</resources>
|
||||
</server>
|
||||
Reference in New Issue
Block a user