Merge branch 'nightly' into ragemp

This commit is contained in:
Vortrex
2022-05-26 17:36:03 -05:00
51 changed files with 1656 additions and 2107 deletions

View File

@@ -1,10 +1,13 @@
{
"sendChat": "true",
"sendConnectEvents": "true",
"sendVehicleEvents": "true",
"sendDeathEvents": "true",
"sendChat": false,
"sendEvents": false,
"sendConnectEvents": false,
"sendVehicleEvents": false,
"sendDeathEvents": false,
"sendAdmin": false,
"webhook": {
"enabled": "true",
"webhookBaseURL": "https://example.com/something.php?message={0}&url={1}"
"enabled": false,
"webhookBaseURL": "http://127.0.0.1:8090/discord.php?message={0}&server={1}&type={2}&pass={3}",
"pass": "LWb7T3ZyCam7Nzen"
}
}

BIN
files/images/flags/fi.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

View File

@@ -149,6 +149,7 @@
<script src="scripts/client/messaging.js" type="client" language="javascript" />
<script src="scripts/client/mousecam.js" type="client" language="javascript" />
<script src="scripts/client/nametag.js" type="client" language="javascript" />
<script src="scripts/client/npc.js" type="client" language="javascript" />
<script src="scripts/client/radio.js" type="client" language="javascript" />
<script src="scripts/client/scoreboard.js" type="client" language="javascript" />
<script src="scripts/client/server.js" type="client" language="javascript" />

View File

@@ -139,7 +139,7 @@ function makePedStopAnimation(pedId) {
/**
* @param {number} animationSlot - The slot index of the animation
* @return {Array} The animation's data (array)
* @return {AnimationData} The animation's data (array)
*/
function getAnimationData(animationSlot, gameId = getGame()) {
return getGameConfig().animations[gameId][animationSlot];

View File

@@ -27,7 +27,7 @@ class BusinessData {
function receiveBusinessFromServer(businessId, name, entrancePosition, blipModel, pickupModel, hasInterior, hasItems) {
logToConsole(LOG_DEBUG, `[VRR.Business] Received business ${businessId} (${name}) from server`);
if(getGame() == VRR_GAME_GTA_IV) {
if(!areServerElementsSupported()) {
if(getBusinessData(businessId) != false) {
let businessData = getBusinessData(businessId);
businessData.name = name;

View File

@@ -53,19 +53,15 @@ function addAllEventHandlers() {
addEventHandler("OnCameraProcess", onCameraProcess);
addEventHandler("OnMouseWheel", onMouseWheel);
addEventHandler("OnEntityProcess", onEntityProcess);
}
// ===========================================================================
function onResourceStart(event, resource) {
sendResourceStartedSignalToServer();
//setUpInitialGame();
//garbageCollectorInterval = setInterval(collectAllGarbage, 1000*60);
resourceStarted = true;
if(resourceReady == true) {
initClient();
}
}
// ===========================================================================
@@ -78,10 +74,6 @@ function onResourceStop(event, resource) {
function onResourceReady(event, resource) {
sendResourceReadySignalToServer();
resourceReady = true;
if(resourceStarted == true) {
initClient();
}
}
// ===========================================================================
@@ -109,6 +101,7 @@ function onProcess(event, deltaTime) {
processVehicleBurning();
//checkChatBoxAutoHide(); // Will be uncommented on 1.4.0 GTAC update
//processVehicleFires();
}
// ===========================================================================
@@ -245,4 +238,16 @@ function onMouseWheel(event, mouseId, deltaCoordinates, flipped) {
processMouseWheelForChatBox(mouseId, deltaCoordinates, flipped);
}
// ===========================================================================
function onEntityProcess(event, entity) {
if(!isSpawned) {
return false;
}
//if(entity.isType(ELEMENT_PED) && !entity.isType(ELEMENT_PLAYER)) {
// processNPCMovement(entity);
//}
}
// ===========================================================================

View File

@@ -66,11 +66,14 @@ function initGUI() {
guiReady = true;
logToConsole(LOG_DEBUG, `[VRR.GUI] All GUI created successfully!`);
sendNetworkEventToServer("vrr.guiReady", true);
loadLocaleConfig();
loadAllLocaleStrings();
resetGUIStrings();
resetLocaleChooserOptions();
sendNetworkEventToServer("vrr.guiReady", true);
};
// ===========================================================================
@@ -160,106 +163,7 @@ function isAnyGUIActive() {
// ===========================================================================
addNetworkEventHandler("vrr.showCharacterSelect", function(firstName, lastName, cash, clan, lastPlayed, skinId) {
logToConsole(LOG_DEBUG, `[VRR.GUI] Received request from server to show character selection window`);
showCharacterSelectGUI(firstName, lastName, cash, clan, lastPlayed, skinId);
});
// ===========================================================================
addNetworkEventHandler("vrr.switchCharacterSelect", function(firstName, lastName, cash, clan, lastPlayed, skinId) {
logToConsole(LOG_DEBUG, `[VRR.GUI] Received request from server to update character selection window with new info`);
switchCharacterSelectGUI(firstName, lastName, cash, clan, lastPlayed, skinId);
});
// ===========================================================================
addNetworkEventHandler("vrr.showError", function(errorMessage, errorTitle, buttonText) {
logToConsole(LOG_DEBUG, `[VRR.GUI] Received request from server to show error window`);
showError(errorMessage, errorTitle, buttonText);
});
// ===========================================================================
addNetworkEventHandler("vrr.showPrompt", function(promptMessage, promptTitle, yesButtonText, noButtonText) {
logToConsole(LOG_DEBUG, `[VRR.GUI] Received request from server to show prompt window`);
showYesNoPromptGUI(promptMessage, promptTitle, yesButtonText, noButtonText);
});
// ===========================================================================
addNetworkEventHandler("vrr.showInfo", function(infoMessage, buttonText) {
logToConsole(LOG_DEBUG, `[VRR.GUI] Received request from server to show info dialog`);
showInfo(infoMessage, buttonText);
});
// ===========================================================================
addNetworkEventHandler("vrr.loginSuccess", function() {
logToConsole(LOG_DEBUG, `[VRR.GUI] Received signal of successful login from server`);
loginSuccess();
});
// ===========================================================================
addNetworkEventHandler("vrr.characterSelectSuccess", function() {
logToConsole(LOG_DEBUG, `[VRR.GUI] Received signal of successful character selection from server`);
characterSelectSuccess();
setChatWindowEnabled(true);
});
// ===========================================================================
addNetworkEventHandler("vrr.loginFailed", function(remainingAttempts) {
logToConsole(LOG_DEBUG, `[VRR.GUI] Received signal of failed login from server`);
loginFailed(remainingAttempts);
});
// ===========================================================================
addNetworkEventHandler("vrr.registrationSuccess", function() {
logToConsole(LOG_DEBUG, `[VRR.GUI] Received signal of successful registration from server`);
registrationSuccess();
});
// ===========================================================================
addNetworkEventHandler("vrr.registrationFailed", function(errorMessage) {
logToConsole(LOG_DEBUG, `[VRR.GUI] Received signal of failed registration from server`);
registrationFailed(errorMessage);
});
// ===========================================================================
addNetworkEventHandler("vrr.newCharacterFailed", function(errorMessage) {
logToConsole(LOG_DEBUG, `[VRR.GUI] Received signal of failed registration from server`);
newCharacterFailed(errorMessage);
});
// ===========================================================================
addNetworkEventHandler("vrr.changePassword", function() {
logToConsole(LOG_DEBUG, `[VRR.GUI] Received signal to change password from server`);
showChangePasswordGUI();
});
// ===========================================================================
addNetworkEventHandler("vrr.showResetPasswordCodeInput", function() {
logToConsole(LOG_DEBUG, `[VRR.GUI] Received signal to input reset password code from server`);
resetPasswordCodeInputGUI();
});
// ===========================================================================
addNetworkEventHandler("vrr.showLocaleChooser", function() {
logToConsole(LOG_DEBUG, `[VRR.GUI] Received signal to show locale chooser from server`);
showLocaleChooserGUI();
});
// ===========================================================================
addNetworkEventHandler("vrr.guiColour", function(red1, green1, blue1, red2, green2, blue2, red3, green3, blue3) {
function setGUIColours(red1, green1, blue1, red2, green2, blue2, red3, green3, blue3) {
logToConsole(LOG_DEBUG, `[VRR.GUI] Received new GUI colours from server: ${red1}, ${green1}, ${blue1} / ${red2}, ${green2}, ${blue2} / ${red3}, ${green3}, ${blue3}`);
primaryColour = [red1, green1, blue1];
secondaryColour = [red2, green2, blue2];
@@ -267,15 +171,7 @@ addNetworkEventHandler("vrr.guiColour", function(red1, green1, blue1, red2, gree
focusedColour = [red1+focusedColourOffset, green1+focusedColourOffset, blue1+focusedColourOffset];
initGUI();
});
// ===========================================================================
addNetworkEventHandler("vrr.guiInit", function() {
logToConsole(LOG_DEBUG, `[VRR.GUI] Initializing MexUI app`);
//initGUI();
sendNetworkEventToServer("vrr.guiReady", true);
});
}
// ===========================================================================

View File

@@ -133,16 +133,17 @@ function checkChangePassword() {
// ===========================================================================
function showChangePasswordGUI() {
function showChangePasswordGUI(errorMessage) {
logToConsole(LOG_DEBUG, `[VRR.GUI] Showing change password window`);
closeAllWindows();
setChatWindowEnabled(false);
mexui.setInput(true);
passwordChange.window.shown = true;
passwordChange.messageLabel = errorMessage;
mexui.focusedControl = passwordChange.passwordInput;
guiSubmitKey = checkChangePassword;
showLocaleChooserGUI();
showLocaleChooserGUI(new Vec2(getScreenWidth()/2-(localeChooser.window.size.x/2), passwordChange.window.position.y+passwordChange.window.size.y+20));
}
// ===========================================================================

View File

@@ -171,7 +171,7 @@ function showCharacterSelectGUI(firstName, lastName, cash, clan, lastPlayed, ski
guiLeftKey = selectPreviousCharacter;
guiRightKey = selectNextCharacter;
showLocaleChooserGUI();
showLocaleChooserGUI(new Vec2(getScreenWidth()/2-(localeChooser.window.size.x/2), characterSelect.window.position.y+characterSelect.window.size.y+20));
}
// ===========================================================================

View File

@@ -17,7 +17,7 @@ let errorDialog = {
function initErrorDialogGUI() {
logToConsole(LOG_DEBUG, `[VRR.GUI] Creating error GUI ...`);
errorDialog.window = mexui.window(game.width/2-200, game.height/2-70, 500, 140, 'ERROR', {
errorDialog.window = mexui.window(getScreenWidth()/2-200, getScreenHeight()/2-70, 400, 140, 'ERROR', {
main: {
backgroundColour: toColour(secondaryColour[0], secondaryColour[1], secondaryColour[2], windowAlpha),
transitionTime: 500,
@@ -34,7 +34,7 @@ function initErrorDialogGUI() {
},
});
errorDialog.messageLabel = errorDialog.window.text(15, 50, 470, 75, 'Error Message', {
errorDialog.messageLabel = errorDialog.window.text(15, 50, 370, 20, 'Error Message', {
main: {
textSize: 10.0,
textAlign: 0.5,
@@ -70,7 +70,7 @@ function showErrorGUI(errorMessage, errorTitle, buttonText) {
mexui.setInput(true);
errorDialog.messageLabel.text = errorMessage;
errorDialog.okayButton.text = buttonText;
errprDialog.window.title = errorTitle;
errorDialog.window.title = errorTitle;
errorDialog.window.shown = true;
}

View File

@@ -17,7 +17,7 @@ let infoDialog = {
function initInfoDialogGUI() {
logToConsole(LOG_DEBUG, `[VRR.GUI] Creating info dialog GUI ...`);
infoDialog.window = mexui.window(game.width/2-200, game.height/2-70, 400, 140, 'Information', {
infoDialog.window = mexui.window(getScreenWidth()/2-200, getScreenHeight()/2-70, 400, 140, 'Information', {
main: {
backgroundColour: toColour(secondaryColour[0], secondaryColour[1], secondaryColour[2], windowAlpha),
},
@@ -70,7 +70,7 @@ function closeInfoDialog() {
// ===========================================================================
function showInfo(infoMessage, infoTitle, buttonText) {
function showInfoGUI(infoMessage, infoTitle, buttonText) {
closeAllWindows();
logToConsole(LOG_DEBUG, `[VRR.GUI] Showing info dialog window. Info: ${infoTitle} - ${infoMessage}`);
mexui.setInput(true);

View File

@@ -52,8 +52,8 @@ function closeLocaleChooserGUI() {
// ===========================================================================
function showLocaleChooserGUI(position = toVector2(0, 0)) {
if(position.x != 0 && position.y != 0) {
function showLocaleChooserGUI(position = toVector2(0.0, 0.0)) {
if(position.x != 0.0 && position.y != 0.0) {
localeChooser.window.position = position;
} else {
localeChooser.window.position = toVector2((getScreenWidth()/2)-(localeChooser.window.size.x/2), getScreenHeight()-100);

View File

@@ -43,7 +43,7 @@ let loginHTML =
function initLoginGUI() {
logToConsole(LOG_DEBUG, `[VRR.GUI] Creating login GUI ...`);
login.window = mexui.window(game.width/2-150, game.height/2-135, 300, 275, 'LOGIN', {
login.window = mexui.window(getScreenWidth()/2-150, getScreenHeight()/2-135, 300, 275, 'LOGIN', {
main: {
backgroundColour: toColour(secondaryColour[0], secondaryColour[1], secondaryColour[2], windowAlpha),
transitionTime: 500,
@@ -118,7 +118,7 @@ function initLoginGUI() {
},
}, checkLogin);
login.forgotPasswordButton = login.window.button(200, 240, 80, 15, 'RESET PASS', {
login.forgotPasswordButton = login.window.button(180, 240, 100, 15, 'RESET PASS', {
main: {
backgroundColour: toColour(primaryColour[0], primaryColour[1], primaryColour[2], buttonAlpha),
textColour: toColour(0, 0, 0, 255),
@@ -131,7 +131,7 @@ function initLoginGUI() {
},
}, switchToPasswordResetGUI);
login.resetPasswordLabel = login.window.text(125, 240, 60, 15, 'Forgot your password?', {
login.resetPasswordLabel = login.window.text(110, 240, 60, 15, 'Forgot your password?', {
main: {
textSize: 8.0,
textAlign: 1.0,
@@ -157,7 +157,7 @@ function showLoginGUI() {
mexui.focusedControl = login.passwordInput;
guiSubmitKey = checkLogin;
showLocaleChooserGUI();
showLocaleChooserGUI(new Vec2(getScreenWidth()/2-(localeChooser.window.size.x/2), login.window.position.y+login.window.size.y+20));
//showSmallGameMessage(`If you don't have a mouse cursor, press ${toUpperCase(getKeyNameFromId(disableGUIKey))} to disable GUI`, COLOUR_WHITE, 7500);
}

View File

@@ -20,7 +20,7 @@ let newCharacter = {
function initNewCharacterGUI() {
logToConsole(LOG_DEBUG, `[VRR.GUI] Creating new character GUI ...`);
newCharacter.window = mexui.window(game.width/2-130, game.height/2-115, 300, 230, 'NEW CHARACTER', {
newCharacter.window = mexui.window(getScreenWidth()/2-130, getScreenHeight()/2-115, 300, 230, 'NEW CHARACTER', {
main: {
backgroundColour: toColour(secondaryColour[0], secondaryColour[1], secondaryColour[2], windowAlpha),
transitionTime: 500,
@@ -158,9 +158,9 @@ function showNewCharacterGUI() {
mexui.setInput(true);
newCharacter.window.shown = true;
mexui.focusedInput = newCharacter.firstNameInput;
guiSubmitButton = checkNewCharacter;
guiSubmitKey = checkNewCharacter;
showLocaleChooserGUI();
showLocaleChooserGUI(new Vec2(getScreenWidth()/2-(localeChooser.window.size.x/2), newCharacter.window.position.y+newCharacter.window.size.y+20));
}
// ===========================================================================

View File

@@ -21,7 +21,7 @@ let register = {
function initRegisterGUI() {
logToConsole(LOG_DEBUG, `[VRR.GUI] Creating register GUI ...`);
register.window = mexui.window(game.width/2-150, game.height/2-150, 300, 300, 'Register', {
register.window = mexui.window(getScreenWidth()/2-150, getScreenHeight()/2-150, 300, 300, 'Register', {
main: {
backgroundColour: toColour(secondaryColour[0], secondaryColour[1], secondaryColour[2], windowAlpha),
transitionTime: 500,
@@ -162,7 +162,7 @@ function showRegistrationGUI() {
mexui.focusedControl = register.passwordInput;
guiSubmitKey = checkRegistration;
showLocaleChooserGUI();
showLocaleChooserGUI(new Vec2(getScreenWidth()/2-(localeChooser.window.size.x/2), register.window.position.y+register.window.size.y+20));
//showSmallGameMessage(`If you don't have a mouse cursor, press ${toUpperCase(getKeyNameFromId(disableGUIKey))} to disable GUI`, COLOUR_WHITE, 7500);
}

View File

@@ -21,7 +21,7 @@ let passwordReset = {
function initResetPasswordGUI() {
logToConsole(LOG_DEBUG, `[VRR.GUI] Creating password reset GUI ...`);
passwordReset.window = mexui.window(game.width/2-150, game.height/2-130, 300, 260, 'RESET PASSWORD', {
passwordReset.window = mexui.window(getScreenWidth()/2-150, getScreenHeight()/2-135, 300, 275, 'RESET PASSWORD', {
main: {
backgroundColour: toColour(secondaryColour[0], secondaryColour[1], secondaryColour[2], windowAlpha),
transitionTime: 500,
@@ -42,7 +42,7 @@ function initResetPasswordGUI() {
passwordReset.window.titleBarHeight = 0;
passwordReset.window.titleBarShown = false;
passwordReset.logoImage = passwordReset.window.image(5, 20, 290, 80, mainLogoPath, {
passwordReset.logoImage = passwordReset.window.image(100, 20, 100, 100, mainLogoPath, {
focused: {
borderColour: toColour(0, 0, 0, 0),
},
@@ -82,7 +82,7 @@ function initResetPasswordGUI() {
});
passwordReset.emailInput.placeholder = "Email";
passwordReset.resetPasswordButton = passwordReset.window.button(20, 205, 260, 30, 'RESET PASSWORD', {
passwordReset.resetPasswordButton = passwordReset.window.button(180, 240, 100, 15, 'RESET PASSWORD', {
main: {
backgroundColour: toColour(primaryColour[0], primaryColour[1], primaryColour[2], buttonAlpha),
textColour: toColour(primaryTextColour[0], primaryTextColour[1], primaryTextColour[2], 255),
@@ -108,7 +108,7 @@ function initResetPasswordGUI() {
},
}, switchToLoginGUI);
passwordReset.backToLoginLabel = passwordReset.window.text(125, 240, 60, 15, 'Remember your password?', {
passwordReset.backToLoginLabel = passwordReset.window.text(110, 240, 60, 15, 'Remember your password?', {
main: {
textSize: 8.0,
textAlign: 1.0,
@@ -132,9 +132,9 @@ function showResetPasswordGUI() {
mexui.setInput(true);
passwordReset.window.shown = true;
mexui.focusedControl = passwordReset.emailInput;
guiSubmitButton = checkResetPassword;
guiSubmitKey = checkResetPassword;
showLocaleChooserGUI();
showLocaleChooserGUI(new Vec2(getScreenWidth()/2-(localeChooser.window.size.x/2), passwordReset.window.position.y+passwordReset.window.size.y+20));
//showSmallGameMessage(`If you don't have a mouse cursor, press ${toUpperCase(getKeyNameFromId(disableGUIKey))} to disable GUI`, COLOUR_WHITE, 7500);
}
@@ -157,15 +157,31 @@ function resetPasswordFailed(errorMessage) {
// ===========================================================================
function resetPasswordCodeInputGUI() {
logToConsole(LOG_DEBUG, `[VRR.GUI] Server reports password reset was successful`);
passwordReset.messageLabel.text = "Check your email for a verification code";
passwordReset.messageLabel.styles.main.textColour = toColour(180, 32, 32, 255);
passwordReset.emailInput.text = "";
passwordReset.emailInput.placeholder = "Verification Code";
guiSubmitButton = checkResetPassword;
logToConsole(LOG_DEBUG|LOG_WARN, `[VRR.GUI] Server reports password reset email confirmation was successful. Asking for code ...`);
closeAllWindows();
passwordReset.messageLabel.text = getLocaleString("GUIResetPasswordCodeInputLabel");
//passwordReset.messageLabel.styles.main.textColour = toColour(180, 32, 32, 255);
passwordReset.emailInput.text = "";
passwordReset.emailInput.placeholder = getLocaleString("GUIResetPasswordCodePlaceholder");
guiSubmitKey = checkResetPassword;
showResetPasswordGUI();
}
// ===========================================================================
function resetPasswordEmailInputGUI() {
logToConsole(LOG_DEBUG|LOG_WARN, `[VRR.GUI] Server reports password reset request was approved. Asking for email ...`);
closeAllWindows();
passwordReset.messageLabel.text = getLocaleString("GUIResetPasswordConfirmEmailLabel");
//passwordReset.messageLabel.styles.main.textColour = toColour(180, 32, 32, 255);
passwordReset.emailInput.text = "";
passwordReset.emailInput.placeholder = getLocaleString("GUIResetPasswordEmailPlaceholder");
guiSubmitKey = checkResetPassword;
showResetPasswordGUI();
}
// ===========================================================================

View File

@@ -8,9 +8,10 @@
// ===========================================================================
class HouseData {
constructor(houseId, entrancePosition, blipModel, pickupModel, hasInterior) {
constructor(houseId, description, entrancePosition, blipModel, pickupModel, hasInterior) {
this.index = -1;
this.houseId = houseId;
this.description = description;
this.entrancePosition = entrancePosition;
this.blipModel = blipModel;
this.pickupModel = pickupModel;
@@ -21,12 +22,13 @@ class HouseData {
// ===========================================================================
function receiveHouseFromServer(houseId, entrancePosition, blipModel, pickupModel, hasInterior) {
function receiveHouseFromServer(houseId, description, entrancePosition, blipModel, pickupModel, hasInterior) {
logToConsole(LOG_DEBUG, `[VRR.House] Received house ${houseId} (${name}) from server`);
if(getGame() == VRR_GAME_GTA_IV) {
if(!areServerElementsSupported()) {
if(getHouseData(houseId) != false) {
let houseData = getHouseData(houseId);
houseData.description = description;
houseData.entrancePosition = entrancePosition;
houseData.blipModel = blipModel;
houseData.pickupModel = pickupModel;
@@ -65,7 +67,7 @@ function receiveHouseFromServer(houseId, entrancePosition, blipModel, pickupMode
}
} else {
logToConsole(LOG_DEBUG, `[VRR.House] House ${houseId} doesn't exist. Adding ...`);
let tempHouseData = new HouseData(houseId, entrancePosition, blipModel, pickupModel, hasInterior);
let tempHouseData = new HouseData(houseId, description, entrancePosition, blipModel, pickupModel, hasInterior);
if(blipModel != -1) {
let blipId = createGameBlip(tempHouseData.blipModel, tempHouseData.entrancePosition, "House");
if(blipId != -1) {

View File

@@ -139,7 +139,7 @@ function drawNametag(x, y, health, armour, text, ping, alpha, distance, colour,
// ===========================================================================
function updateNametags(element) {
function updateNametag(element) {
if(!areWorldLabelsSupported()) {
return false;
}
@@ -147,10 +147,11 @@ function updateNametags(element) {
if(localPlayer != null) {
let playerPos = localPlayer.position;
let elementPos = element.position;
let client = getClientFromPlayerElement(element);
elementPos[2] += 0.9;
//if(typeof element.getComponentPosition()) {
let screenPos = getScreenFromWorldPosition(elementPos);
if (screenPos[2] >= 0.0) {
let health = element.health/100.0;
@@ -178,20 +179,22 @@ function updateNametags(element) {
let paused = false;
let ping = -1;
if(typeof playerNames[element.name] != "undefined") {
name = playerNames[element.name];
}
if(element.isType(ELEMENT_PLAYER)) {
if(typeof playerNames[element.name] != "undefined") {
name = playerNames[element.name];
}
if(typeof playerPaused[element.name] != "undefined") {
paused = playerPaused[element.name];
}
if(typeof playerPaused[element.name] != "undefined") {
paused = playerPaused[element.name];
}
if(typeof playerColours[element.name] != "undefined") {
colour = playerColours[element.name];
}
if(typeof playerColours[element.name] != "undefined") {
colour = playerColours[element.name];
}
if(typeof playerPing[element.name] != "undefined") {
ping = playerPing[element.name];
if(typeof playerPing[element.name] != "undefined") {
ping = playerPing[element.name];
}
}
drawNametag(screenPos[0], screenPos[1], health, armour, name, ping, 1.0-distance/nametagDistance, distance, colour, paused, element.skin);
@@ -218,9 +221,9 @@ function processNameTagRendering(event) {
// return false;
//}
getElementsByType(ELEMENT_PLAYER).forEach(function(player) {
if(player != localPlayer) {
updateNametags(player);
getElementsByType(ELEMENT_PED).forEach(function(ped) {
if(ped != localPlayer) {
updateNametag(ped);
}
});
}

View File

@@ -155,6 +155,12 @@ function getClosestCivilian(position) {
// ===========================================================================
function getClosestPlayer(position) {
return getElementsByType(ELEMENT_PLAYER).reduce((i, j) => ((i.position.distance(position) <= j.position.distance(position)) ? i : j));
}
// ===========================================================================
function is2dPositionOnScreen(pos2d) {
return pos2d.x >= 0 && pos2d.y >= 0 && pos2d.x <= game.width && pos2d.y <= game.height;
}
@@ -674,4 +680,21 @@ function setPedInvincible(ped, state) {
ped.invincible = state;
}
// ===========================================================================
function setPedLookAt(ped, position) {
if(getGame() == VRR_GAME_GTA_SA) {
ped.lookAt(position, 10000);
return true;
} else {
setElementHeading(ped.id, getHeadingFromPosToPos(getElementPosition(ped.id), position));
}
}
// ===========================================================================
function setElementHeading(elementId, heading) {
getElementFromId(elementId).heading = heading;
}
// ===========================================================================

19
scripts/client/npc.js Normal file
View File

@@ -0,0 +1,19 @@
// ===========================================================================
// Vortrex's Roleplay Resource
// https://github.com/VortrexFTW/gtac_roleplay
// ===========================================================================
// FILE: npc.js
// DESC: Provides NPC functions and processing
// TYPE: Client (JavaScript)
// ===========================================================================
function processNPCMovement(npc) {
//if(npc.isSyncer == true) {
if(getEntityData(npc, "vrr.lookAtClosestPlayer") == true) {
let closestPlayer = getClosestPlayer(getElementPosition(npc.id));
setPedLookAt(npc, getElementPosition(closestPlayer.id));
}
//}
}
// ===========================================================================

View File

@@ -86,6 +86,23 @@ function addAllNetworkHandlers() {
addNetworkEventHandler("vrr.showNewCharacter", showNewCharacterGUI);
addNetworkEventHandler("vrr.showLogin", showLoginGUI);
addNetworkEventHandler("vrr.2fa", showTwoFactorAuthGUI);
addNetworkEventHandler("vrr.showResetPasswordCodeInput", resetPasswordCodeInputGUI);
addNetworkEventHandler("vrr.showResetPasswordEmailInput", resetPasswordEmailInputGUI);
addNetworkEventHandler("vrr.showChangePassword", showChangePasswordGUI);
addNetworkEventHandler("vrr.showCharacterSelect", showCharacterSelectGUI);
addNetworkEventHandler("vrr.switchCharacterSelect", switchCharacterSelectGUI);
addNetworkEventHandler("vrr.showError", showErrorGUI);
addNetworkEventHandler("vrr.showInfo", showInfoGUI);
addNetworkEventHandler("vrr.showPrompt", showYesNoPromptGUI);
addNetworkEventHandler("vrr.loginSuccess", loginSuccess);
addNetworkEventHandler("vrr.characterSelectSuccess", characterSelectSuccess);
addNetworkEventHandler("vrr.loginFailed", loginFailed);
addNetworkEventHandler("vrr.registrationSuccess", registrationSuccess);
addNetworkEventHandler("vrr.registrationFailed", registrationFailed);
addNetworkEventHandler("vrr.newCharacterFailed", newCharacterFailed);
addNetworkEventHandler("vrr.changePassword", showChangePasswordGUI);
addNetworkEventHandler("vrr.showLocaleChooser", showLocaleChooserGUI);
addNetworkEventHandler("vrr.guiColour", setGUIColours);
// Business
addNetworkEventHandler("vrr.business", receiveBusinessFromServer);
@@ -121,9 +138,9 @@ function addAllNetworkHandlers() {
addNetworkEventHandler("vrr.nametag", updatePlayerNameTag);
addNetworkEventHandler("vrr.nametagDistance", setNameTagDistance);
addNetworkEventHandler("vrr.ping", updatePlayerPing);
addNetworkEventHandler("vrr.pedAnim", makePedPlayAnimation);
addNetworkEventHandler("vrr.pedStopAnim", makePedStopAnimation);
addNetworkEventHandler("vrr.forcePedAnim", forcePedAnimation);
addNetworkEventHandler("vrr.anim", makePedPlayAnimation);
addNetworkEventHandler("vrr.stopAnim", makePedStopAnimation);
addNetworkEventHandler("vrr.forceAnim", forcePedAnimation);
addNetworkEventHandler("vrr.clientInfo", serverRequestedClientInfo);
addNetworkEventHandler("vrr.interiorLights", updateInteriorLightsState);
addNetworkEventHandler("vrr.cutsceneInterior", setCutsceneInterior);
@@ -184,11 +201,23 @@ function set2DRendering(hudState, labelState, smallGameMessageState, scoreboardS
function onServerSpawnedLocalPlayer(state) {
logToConsole(LOG_DEBUG, `[VRR.Main] Setting spawned state to ${state}`);
isSpawned = state;
setUpInitialGame();
if(state) {
setUpInitialGame();
setTimeout(function() {
calledDeathEvent = false;
}, 1000);
getPeds().filter(ped => !ped.isType(ELEMENT_PLAYER)).forEach(ped => {
syncCivilianProperties(ped);
});
getPlayers().forEach(player => {
syncPlayerProperties(player);
});
getVehicles().forEach(veh => {
syncVehicleProperties(veh);
});
}
}

View File

@@ -25,168 +25,175 @@ function initClientScripts() {
// ===========================================================================
function setUpInitialGame() {
switch(getGame()) {
case [VRR_GAME_GTA_III]: {
game.SET_PLAYER_NEVER_GETS_TIRED(game.GET_PLAYER_ID(), 0);
game.setGameStat(STAT_PROGRESSMADE, 9999);
game.setGameStat(STAT_TOTALPROGRESSINGAME, 9999);
//game.SET_CAR_DENSITY_MULTIPLIER(3.0); // No visual effect. Needs tweaking and testing.
//game.SET_PED_DENSITY_MULTIPLIER(3.0); // No visual effect. Needs tweaking and testing.
game.onMission = true; // Disables taxi/vigilante/etc and other start mission triggers
SetStandardControlsEnabled(true); // Provided by mouse camera script (mousecam.js)
break;
}
if(getGame() == VRR_GAME_GTA_III) {
logToConsole(LOG_DEBUG|LOG_WARN, "Setting up initial game stuff for GTA III ...");
case [VRR_GAME_GTA_VC]: {
game.SET_PLAYER_NEVER_GETS_TIRED(game.GET_PLAYER_ID(), 0);
game.setGameStat(STAT_PROGRESSMADE, 9999);
game.setGameStat(STAT_TOTALPROGRESSINGAME, 9999);
//game.SET_CAR_DENSITY_MULTIPLIER(3.0); // No visual effect. Needs tweaking and testing.
//game.SET_PED_DENSITY_MULTIPLIER(3.0); // No visual effect. Needs tweaking and testing.
// Turn off unlimited sprint
game.SET_PLAYER_NEVER_GETS_TIRED(game.GET_PLAYER_ID(), 0);
game.REQUEST_ANIMATION("bikev");
game.REQUEST_ANIMATION("bikeh");
game.REQUEST_ANIMATION("biked");
game.REQUEST_ANIMATION("knife");
game.REQUEST_ANIMATION("python");
game.REQUEST_ANIMATION("shotgun");
game.REQUEST_ANIMATION("buddy");
game.REQUEST_ANIMATION("tec");
game.REQUEST_ANIMATION("uzi");
game.REQUEST_ANIMATION("rifle");
game.REQUEST_ANIMATION("m60");
game.REQUEST_ANIMATION("sniper");
game.REQUEST_ANIMATION("grenade");
game.REQUEST_ANIMATION("flame");
game.REQUEST_ANIMATION("medic");
game.REQUEST_ANIMATION("sunbathe");
//game.REQUEST_ANIMATION("playidles");
game.REQUEST_ANIMATION("riot");
game.REQUEST_ANIMATION("strip");
game.REQUEST_ANIMATION("lance");
game.REQUEST_ANIMATION("skate");
// Set completed game progress
game.setGameStat(STAT_PROGRESSMADE, 9999);
game.setGameStat(STAT_TOTALPROGRESSINGAME, 9999);
game.LOAD_ALL_MODELS_NOW();
game.onMission = true; // Disables taxi/vigilante/etc and other start mission triggers
SetStandardControlsEnabled(true); // Provided by mouse camera script (mousecam.js)
break;
}
// Traffic and ped density
//game.SET_CAR_DENSITY_MULTIPLIER(3.0); // No visual effect. Needs tweaking and testing.
//game.SET_PED_DENSITY_MULTIPLIER(3.0); // No visual effect. Needs tweaking and testing.
case [VRR_GAME_GTA_SA]: {
game.setGameStat(STAT_WEAPONTYPE_PISTOL_SKILL, 400);
game.setGameStat(STAT_WEAPONTYPE_PISTOL_SILENCED_SKILL, 400);
game.setGameStat(STAT_WEAPONTYPE_DESERT_EAGLE_SKILL, 400);
game.setGameStat(STAT_WEAPONTYPE_SHOTGUN_SKILL, 400);
game.setGameStat(STAT_WEAPONTYPE_SAWNOFF_SHOTGUN_SKILL, 400);
game.setGameStat(STAT_WEAPONTYPE_SPAS12_SHOTGUN_SKILL, 400);
game.setGameStat(STAT_WEAPONTYPE_MICRO_UZI_SKILL, 400);
game.setGameStat(STAT_WEAPONTYPE_MP5_SKILL, 400);
game.setGameStat(STAT_WEAPONTYPE_AK47_SKILL, 400);
game.setGameStat(STAT_WEAPONTYPE_M4_SKILL, 400);
game.setGameStat(STAT_DRIVING_SKILL, 9999);
game.setGameStat(STAT_FAT, 9999);
game.setGameStat(STAT_ENERGY, 9999);
game.setGameStat(STAT_CYCLE_SKILL, 9999);
game.setGameStat(STAT_BIKE_SKILL, 9999);
game.setGameStat(STAT_GAMBLING, 9999);
game.setGameStat(STAT_PROGRESS_MADE, 9999);
game.setGameStat(STAT_RESPECT, 0);
game.setGameStat(STAT_RESPECT_TOTAL, 0);
game.setGameStat(STAT_SEX_APPEAL, 0);
game.setGameStat(STAT_STAMINA, 9999);
game.setGameStat(STAT_TOTAL_PROGRESS, 9999);
game.setGameStat(STAT_UNDERWATER_STAMINA, 9999);
game.setGameStat(STAT_BODY_MUSCLE, 9999);
// Disables taxi/vigilante/etc and other start mission triggers
game.onMission = true;
game.setDefaultInteriors(false); // Disables default yellow cone at doors for entering places in singleplayer
game.onMission = true; // Disables taxi/vigilante/etc and other start mission triggers
break;
}
// Provided by mouse camera script (mousecam.js)
SetStandardControlsEnabled(true);
} else if(getGame() == VRR_GAME_GTA_VC) {
logToConsole(LOG_DEBUG|LOG_WARN, "Setting up initial game stuff for GTA Vice City ...");
case [VRR_GAME_GTA_IV]: {
natives.allowEmergencyServices(false);
natives.setCreateRandomCops(true);
natives.setMaxWantedLevel(0);
natives.setWantedMultiplier(0.0);
natives.allowPlayerToCarryNonMissionObjects(natives.getPlayerId(), true);
natives.setPlayerTeam(natives.getPlayerId(), 0);
natives.loadAllObjectsNow();
natives.setCellphoneRanked(false);
natives.setOverrideNoSprintingOnPhoneInMultiplayer(false);
natives.setSyncWeatherAndGameTime(false);
natives.usePlayerColourInsteadOfTeamColour(true);
natives.disablePauseMenu(true);
//natives.allowReactionAnims(localPlayer, false);
natives.allowGameToPauseForStreaming(false);
natives.allowStuntJumpsToTrigger(false);
natives.setPickupsFixCars(false);
natives.forceFullVoice(localPlayer);
// Turn off unlimited sprint
game.SET_PLAYER_NEVER_GETS_TIRED(game.GET_PLAYER_ID(), 0);
// HUD and Display
//natives.displayCash(false);
//natives.displayAmmo(false);
//natives.displayHud(false);
//natives.displayRadar(false);
//natives.displayAreaName(false);
natives.displayPlayerNames(true);
natives.setPoliceRadarBlips(false);
natives.removeTemporaryRadarBlipsForPickups();
natives.displayNonMinigameHelpMessages(false);
natives.setDisplayPlayerNameAndIcon(natives.getPlayerId(), true);
// Set completed game progress
game.setGameStat(STAT_PROGRESSMADE, 99999);
game.setGameStat(STAT_TOTALPROGRESSINGAME, 99999);
// Item/Money Dropping
natives.setMoneyCarriedByAllNewPeds(0);
natives.setDeadPedsDropWeapons(false);
natives.setPlayersDropMoneyInNetworkGame(false);
// Traffic and ped density
//game.SET_CAR_DENSITY_MULTIPLIER(3.0); // No visual effect. Needs tweaking and testing.
//game.SET_PED_DENSITY_MULTIPLIER(3.0); // No visual effect. Needs tweaking and testing.
// Population
//natives.dontSuppressAnyCarModels(5.0);
//natives.dontSuppressAnyPedModels(5.0);
//natives.forceGenerateParkedCarsTooCloseToOthers(true);
//natives.setParkedCarDensityMultiplier(5.0);
//natives.setRandomCarDensityMultiplier(5.0);
//natives.setPedDensityMultiplier(5.0);
//natives.setCarDensityMultiplier(5.0);
//natives.setScenarioPedDensityMultiplier(5.0, 5.0);
natives.switchRandomTrains(true);
natives.switchRandomBoats(true);
natives.switchAmbientPlanes(true);
natives.switchMadDrivers(false);
// Load all anim libs
game.REQUEST_ANIMATION("bikev");
game.REQUEST_ANIMATION("bikeh");
game.REQUEST_ANIMATION("biked");
game.REQUEST_ANIMATION("knife");
game.REQUEST_ANIMATION("python");
game.REQUEST_ANIMATION("shotgun");
game.REQUEST_ANIMATION("buddy");
game.REQUEST_ANIMATION("tec");
game.REQUEST_ANIMATION("uzi");
game.REQUEST_ANIMATION("rifle");
game.REQUEST_ANIMATION("m60");
game.REQUEST_ANIMATION("sniper");
game.REQUEST_ANIMATION("grenade");
game.REQUEST_ANIMATION("flame");
game.REQUEST_ANIMATION("medic");
game.REQUEST_ANIMATION("sunbathe");
//game.REQUEST_ANIMATION("playidles");
game.REQUEST_ANIMATION("riot");
game.REQUEST_ANIMATION("strip");
game.REQUEST_ANIMATION("lance");
game.REQUEST_ANIMATION("skate");
// Singleplayer Cellphone
//natives.requestScript("spcellphone");
//natives.startNewScript("spcellphone", 0);
// Script "v-blockedscripts" blocks the mpcellphone scripts
natives.setMessagesWaiting(false); // Seems to have no effect
natives.setMobilePhoneRadioState(false);
//game.LOAD_ALL_MODELS_NOW();
// Disables taxi/vigilante/etc and other start mission triggers
game.onMission = true;
// Animation libraries
natives.requestAnims("DANCING");
// Provided by mouse camera script (mousecam.js)
SetStandardControlsEnabled(true);
} else if(getGame() == VRR_GAME_GTA_SA) {
logToConsole(LOG_DEBUG|LOG_WARN, "Setting up initial game stuff for GTA San Andreas ...");
// Turn weapon skills down a bit
game.setGameStat(STAT_WEAPONTYPE_PISTOL_SKILL, 400);
game.setGameStat(STAT_WEAPONTYPE_PISTOL_SILENCED_SKILL, 400);
game.setGameStat(STAT_WEAPONTYPE_DESERT_EAGLE_SKILL, 400);
game.setGameStat(STAT_WEAPONTYPE_SHOTGUN_SKILL, 400);
game.setGameStat(STAT_WEAPONTYPE_SAWNOFF_SHOTGUN_SKILL, 400);
game.setGameStat(STAT_WEAPONTYPE_SPAS12_SHOTGUN_SKILL, 400);
game.setGameStat(STAT_WEAPONTYPE_MICRO_UZI_SKILL, 400);
game.setGameStat(STAT_WEAPONTYPE_MP5_SKILL, 400);
game.setGameStat(STAT_WEAPONTYPE_AK47_SKILL, 400);
game.setGameStat(STAT_WEAPONTYPE_M4_SKILL, 400);
// Some last steps
//natives.loadAllObjectsNow();
break;
}
// Pro driving skill
game.setGameStat(STAT_DRIVING_SKILL, 9999);
case VRR_GAME_MAFIA_ONE: {
game.mapEnabled = false;
game.setTrafficEnabled(false);
break;
}
// Only visual for CJ, but affects all peds fight speed, bicycle hop, etc
game.setGameStat(STAT_FAT, 9999);
game.setGameStat(STAT_ENERGY, 9999);
game.setGameStat(STAT_CYCLE_SKILL, 9999);
game.setGameStat(STAT_BIKE_SKILL, 9999);
game.setGameStat(STAT_GAMBLING, 9999);
game.setGameStat(STAT_PROGRESS_MADE, 9999);
game.setGameStat(STAT_RESPECT, 0);
game.setGameStat(STAT_RESPECT_TOTAL, 0);
game.setGameStat(STAT_SEX_APPEAL, 0);
game.setGameStat(STAT_STAMINA, 9999);
game.setGameStat(STAT_TOTAL_PROGRESS, 9999);
game.setGameStat(STAT_UNDERWATER_STAMINA, 9999);
game.setGameStat(STAT_BODY_MUSCLE, 9999);
// Disables default yellow cone at doors for entering places in singleplayer
game.setDefaultInteriors(false);
// Disables taxi/vigilante/etc and other start mission triggers
game.onMission = true;
} else if(getGame() == VRR_GAME_GTA_IV) {
natives.allowEmergencyServices(false);
natives.setCreateRandomCops(true);
natives.setMaxWantedLevel(0);
natives.setWantedMultiplier(0.0);
natives.allowPlayerToCarryNonMissionObjects(natives.getPlayerId(), true);
natives.setPlayerTeam(natives.getPlayerId(), 0);
natives.loadAllObjectsNow();
natives.setCellphoneRanked(false);
natives.setOverrideNoSprintingOnPhoneInMultiplayer(false);
natives.setSyncWeatherAndGameTime(false);
natives.usePlayerColourInsteadOfTeamColour(true);
natives.disablePauseMenu(true);
//natives.allowReactionAnims(localPlayer, false);
natives.allowGameToPauseForStreaming(false);
natives.allowStuntJumpsToTrigger(false);
natives.setPickupsFixCars(false);
natives.forceFullVoice(localPlayer);
// HUD and Display
//natives.displayCash(false);
//natives.displayAmmo(false);
//natives.displayHud(false);
//natives.displayRadar(false);
//natives.displayAreaName(false);
natives.displayPlayerNames(true);
natives.setPoliceRadarBlips(false);
natives.removeTemporaryRadarBlipsForPickups();
natives.displayNonMinigameHelpMessages(false);
natives.setDisplayPlayerNameAndIcon(natives.getPlayerId(), true);
// Item/Money Dropping
natives.setMoneyCarriedByAllNewPeds(0);
natives.setDeadPedsDropWeapons(false);
natives.setPlayersDropMoneyInNetworkGame(false);
// Population
//natives.dontSuppressAnyCarModels(5.0);
//natives.dontSuppressAnyPedModels(5.0);
//natives.forceGenerateParkedCarsTooCloseToOthers(true);
//natives.setParkedCarDensityMultiplier(5.0);
//natives.setRandomCarDensityMultiplier(5.0);
//natives.setPedDensityMultiplier(5.0);
//natives.setCarDensityMultiplier(5.0);
//natives.setScenarioPedDensityMultiplier(5.0, 5.0);
natives.switchRandomTrains(true);
natives.switchRandomBoats(true);
natives.switchAmbientPlanes(true);
natives.switchMadDrivers(false);
// Singleplayer Cellphone
//natives.requestScript("spcellphone");
//natives.startNewScript("spcellphone", 0);
// Script "v-blockedscripts" blocks the mpcellphone scripts
natives.setMessagesWaiting(false); // Seems to have no effect
natives.setMobilePhoneRadioState(false);
// Animation libraries
natives.requestAnims("DANCING");
// Some last steps
//natives.loadAllObjectsNow();
} else if(getGame() == VRR_GAME_MAFIA_ONE) {
game.mapEnabled = false;
game.setTrafficEnabled(false);
}
}
// ===========================================================================
function initClient() {
loadLocaleConfig();
loadAllLocaleStrings();
setUpInitialGame();
}
// ===========================================================================
initClientScripts();
// ===========================================================================

View File

@@ -128,10 +128,10 @@ function syncVehicleProperties(vehicle) {
}
if(getGame() == VRR_GAME_GTA_SA) {
let allUpgrades = getGameConfig().vehicleUpgrades[getGame()];
for(let i in allUpgrades) {
vehicle.removeUpgrade(i);
}
//let allUpgrades = getGameConfig().vehicleUpgrades[getGame()];
//for(let i in allUpgrades) {
// vehicle.removeUpgrade(i);
//}
if(doesEntityDataExist(vehicle, "vrr.upgrades")) {
let upgrades = getEntityData(vehicle, "vrr.upgrades");
@@ -246,8 +246,9 @@ function syncCivilianProperties(civilian) {
}
if(doesEntityDataExist(civilian, "vrr.anim")) {
let animData = getEntityData(civilian, "vrr.anim");
civilian.addAnimation(animData[0], animData[1]);
let animationSlot = getEntityData(civilian, "vrr.anim");
let animationData = getAnimationData(animationSlot);
civilian.addAnimation(animationData.groupId, animationData.animId);
}
}
@@ -366,26 +367,6 @@ function syncPlayerProperties(player) {
// ===========================================================================
function syncObjectProperties(object) {
if(!areServerElementsSupported()) {
return false;
}
if(getGame() == VRR_GAME_GTA_III || getGame() == VRR_GAME_GTA_VC) {
if(doesEntityDataExist(object, "vrr.scale")) {
let scaleFactor = getEntityData(object, "vrr.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;
}
}
}
// ===========================================================================
function syncElementProperties(element) {
if(!areServerElementsSupported()) {
return false;
@@ -428,10 +409,6 @@ function syncElementProperties(element) {
syncPlayerProperties(element);
break;
case ELEMENT_OBJECT:
syncObjectProperties(element);
break;
default:
break;
}

View File

@@ -1016,27 +1016,48 @@ function checkAccountResetPasswordRequest(client, inputText) {
return false;
}
if(getPlayerData(client).passwordResetState == VRR_RESETPASS_STATE_NONE) {
if(toLowerCase(getPlayerData(client).accountData.emailAddress) != toLowerCase(inputText)) {
logToConsole(LOG_DEBUG|LOG_WARN, `${getPlayerDisplayForConsole(client)} failed to reset their password (email not correct)`);
return false;
switch(getPlayerData(client).passwordResetState) {
case VRR_RESETPASS_STATE_EMAILCONFIRM: {
if(toLowerCase(getPlayerData(client).accountData.emailAddress) != toLowerCase(inputText)) {
logToConsole(LOG_INFO|LOG_WARN, `${getPlayerDisplayForConsole(client)} failed to reset their password (email not correct)`);
showPlayerErrorGUI(client, getLocaleString(client, "GUIErrorResetPasswordFailedInvalidEmail"), getLocaleString(client, "GUIErrorTitle"), getLocaleString(client, "GUIOkButton"));
return false;
}
let passwordResetCode = toUpperCase(generateEmailVerificationCode());
getPlayerData(client).passwordResetState = VRR_RESETPASS_STATE_CODEINPUT;
getPlayerData(client).passwordResetCode = passwordResetCode;
showPlayerResetPasswordCodeInputGUI(client);
sendPasswordResetEmail(client, passwordResetCode);
logToConsole(LOG_INFO, `${getPlayerDisplayForConsole(client)} submitted successful email for password reset. Sending email and awaiting verification code input ...`);
break;
}
let passwordResetCode = toUpperCase(generateEmailVerificationCode());
getPlayerData(client).passwordResetState = VRR_RESETPASS_STATE_CODEINPUT;
getPlayerData(client).passwordResetCode = passwordResetCode;
sendPasswordResetEmail(client, passwordResetCode);
showPlayerResetPasswordCodeInputGUI(client);
logToConsole(LOG_DEBUG|LOG_WARN, `${getPlayerDisplayForConsole(client)} reset their password. Awaiting verification code input ...`);
} else if(getPlayerData(client).passwordResetState == VRR_RESETPASS_STATE_CODEINPUT) {
if(getPlayerData(client).passwordResetCode == toUpperCase(inputText)) {
getPlayerData(client).passwordResetState = VRR_RESETPASS_STATE_SETPASS;
showPlayerChangePasswordGUI(client);
logToConsole(LOG_DEBUG, `${getPlayerDisplayForConsole(client)} entered the correct reset password verification code. Awaiting new password input ...`);
} else {
getPlayerData(client).passwordResetState = VRR_RESETPASS_STATE_NONE;
disconnectPlayer(client);
logToConsole(LOG_DEBUG|LOG_WARN, `${getPlayerDisplayForConsole(client)} failed to reset their password (verification code not correct)`);
case VRR_RESETPASS_STATE_CODEINPUT: {
if(inputText != "") {
if(getPlayerData(client).passwordResetCode == toUpperCase(inputText)) {
getPlayerData(client).passwordResetState = VRR_RESETPASS_STATE_SETPASS;
showPlayerChangePasswordGUI(client, getLocaleString(client));
logToConsole(LOG_INFO, `${getPlayerDisplayForConsole(client)} entered the correct reset password verification code. Awaiting new password input ...`);
} else {
getPlayerData(client).passwordResetState = VRR_RESETPASS_STATE_NONE;
getPlayerData(client).passwordResetAttemptsRemaining = getPlayerData(client).passwordResetAttemptsRemaining - 1;
logToConsole(LOG_INFO|LOG_WARN, `${getPlayerDisplayForConsole(client)} failed to reset their password (verification code not correct, ${getPlayerData(client).passwordResetAttemptsRemaining} attempts remaining)`);
if(getPlayerData(client).passwordResetAttemptsRemaining <= 0) {
logToConsole(LOG_INFO|LOG_WARN, `${getPlayerDisplayForConsole(client)} failed to reset their password (verification code not correct, no more attempts remaining, kicking ...)`);
disconnectPlayer(client);
return false;
}
}
}
break;
}
case VRR_RESETPASS_STATE_NONE: {
logToConsole(LOG_INFO, `${getPlayerDisplayForConsole(client)} requested a password reset. Awaiting email input ...`);
showPlayerResetPasswordEmailInputGUI(client);
getPlayerData(client).passwordResetState = VRR_RESETPASS_STATE_EMAILCONFIRM;
break;
}
}
@@ -1414,14 +1435,8 @@ function isAccountEmailVerified(accountData) {
// ===========================================================================
function isAccountTwoFactorAuthenticationVerified(accountData) {
return hasBitFlag(accountData.flags.moderation, getModerationFlagValue("TwoFactorAuthVerified"));
}
// ===========================================================================
function doesPlayerHaveTwoFactorAuthEnabled(client) {
return hasBitFlag(getPlayerData(client).accountData.settings, getAccountSettingsFlagValue("TwoFactorAuth"));
return hasBitFlag(getPlayerData(client).accountData.settings, getAccountSettingsFlagValue("TwoStepAuth"));
}
// ===========================================================================

View File

@@ -747,14 +747,14 @@ function getBusinessInfoCommand(command, params, client) {
[`ID`, `${businessData.index}/${businessData.databaseId}`],
[`Owner`, `${ownerName} (${getBusinessOwnerTypeText(businessData.ownerType)})`],
[`Locked`, `${getLockedUnlockedFromBool(businessData.locked)}`],
[`BuyPrice`, `${businessData.buyPrice}`],
[`RentPrice`, `${businessData.rentPrice}`],
[`BuyPrice`, `$${businessData.buyPrice}`],
//[`RentPrice`, `${businessData.rentPrice}`],
[`HasInterior`, `${getYesNoFromBool(businessData.hasInterior)}`],
[`CustomInterior`, `${getYesNoFromBool(businessData.customInterior)}`],
[`HasBuyableItems`, `${getYesNoFromBool(doesBusinessHaveAnyItemsToBuy(businessId))}`],
[`EntranceFee`, `${businessData.entranceFee}`],
[`EntranceFee`, `$${businessData.entranceFee}`],
[`InteriorLights`, `${getOnOffFromBool(businessData.interiorLights)}`],
[`Balance`, `${businessData.till}`],
[`Balance`, `$${businessData.till}`],
[`RadioStation`, `${businessData.streamingRadioStation}`],
[`LabelHelpType`, `${businessData.labelHelpType}`],
];
@@ -940,6 +940,65 @@ function setBusinessInteriorTypeCommand(command, params, client) {
// ===========================================================================
/**
* This is a command handler function.
*
* @param {string} command - The command name used by the player
* @param {string} params - The parameters/args string used with the command by the player
* @param {Client} client - The client/player that used the command
* @return {bool} Whether or not the command was successful
*
*/
function addBusinessPropertyTemplateEntities(command, params, client) {
let propertyTemplateParam = getParam(params, " ", 1) || "business";
let businessId = getPlayerBusiness(client);
if(!getBusinessData(businessId)) {
messagePlayerError(client, getLocaleString(client, "InvalidBusiness"));
return false;
}
if(typeof getGameConfig().interiors[getGame()] == "undefined") {
messagePlayerError(client, `There are no property templates available for this game!`);
return false;
}
if(isNaN(propertyTemplateParam)) {
if(isNull(getGameConfig().interiors[getGame()][typeParam])) {
messagePlayerError(client, "Invalid interior type! Use an interior type name");
let interiorTypesList = Object.keys(getGameConfig().properties[getGame()]);
let chunkedList = splitArrayIntoChunks(interiorTypesList, 10);
messagePlayerNormal(client, makeChatBoxSectionHeader(getLocaleString(client, "HeaderPropertyTemplateTypes")));
for(let i in chunkedList) {
messagePlayerInfo(client, chunkedList[i].join(", "));
}
return false;
}
getBusinessData(businessId).exitPosition = getGameConfig().interiors[getGame()][typeParam][0];
getBusinessData(businessId).exitInterior = getGameConfig().interiors[getGame()][typeParam][1];
getBusinessData(businessId).exitDimension = getBusinessData(businessId).databaseId+getGlobalConfig().businessDimensionStart;
getBusinessData(businessId).exitPickupModel = getGameConfig().pickupModels[getGame()].Exit;
getBusinessData(businessId).hasInterior = true;
getBusinessData(businessId).customInterior = getGameConfig().interiors[getGame()][typeParam][2];
getBusinessData(businessId).interiorCutscene = getGameConfig().interiors[getGame()][typeParam][3];
}
//deleteBusinessExitPickup(businessId);
//deleteBusinessExitBlip(businessId);
//createBusinessExitBlip(businessId);
//createBusinessExitPickup(businessId);
resetBusinessPickups(businessId);
getBusinessData(businessId).needsSaved = true;
messageAdmins(`{adminOrange}${getPlayerName(client)}{MAINCOLOUR} set business {businessBlue}${getBusinessData(businessId).name}{MAINCOLOUR} interior type to {ALTCOLOUR}${typeParam}`);
}
// ===========================================================================
/**
* This is a command handler function.
*
@@ -1649,6 +1708,8 @@ function saveBusinessToDatabase(businessId) {
["biz_label_help_type", tempBusinessData.labelHelpType],
["biz_radiostation", tempBusinessData.streamingRadioStation],
["biz_custom_interior", boolToInt(tempBusinessData.customInterior)],
["biz_buy_price", boolToInt(tempBusinessData.buyPrice)],
//["biz_rent_price", boolToInt(tempBusinessData.rentPrice)],
];
let dbQuery = null;
@@ -1749,24 +1810,33 @@ function createBusinessEntrancePickup(businessId) {
logToConsole(LOG_VERBOSE, `[VRR.Job]: Creating entrance pickup for business ${businessData.name} (model ${pickupModelId})`);
let entrancePickup = createGamePickup(pickupModelId, businessData.entrancePosition, getGameConfig().pickupTypes[getGame()].business);
if(entrancePickup != null) {
if(businessData.entranceDimension != -1) {
setElementDimension(entrancePickup, businessData.entranceDimension);
setElementOnAllDimensions(entrancePickup, false);
} else {
setElementOnAllDimensions(entrancePickup, true);
}
if(areServerElementsSupported()) {
let entrancePickup = createGamePickup(pickupModelId, businessData.entrancePosition, getGameConfig().pickupTypes[getGame()].business);
if(entrancePickup != null) {
if(businessData.entranceDimension != -1) {
setElementDimension(entrancePickup, businessData.entranceDimension);
setElementOnAllDimensions(entrancePickup, false);
} else {
setElementOnAllDimensions(entrancePickup, true);
}
if(getGlobalConfig().businessPickupStreamInDistance == -1 || getGlobalConfig().businessPickupStreamOutDistance == -1) {
entrancePickup.netFlags.distanceStreaming = false;
} else {
setElementStreamInDistance(entrancePickup, getGlobalConfig().businessPickupStreamInDistance);
setElementStreamOutDistance(entrancePickup, getGlobalConfig().businessPickupStreamOutDistance);
if(getGlobalConfig().businessPickupStreamInDistance == -1 || getGlobalConfig().businessPickupStreamOutDistance == -1) {
entrancePickup.netFlags.distanceStreaming = false;
} else {
setElementStreamInDistance(entrancePickup, getGlobalConfig().businessPickupStreamInDistance);
setElementStreamOutDistance(entrancePickup, getGlobalConfig().businessPickupStreamOutDistance);
}
setElementTransient(entrancePickup, false);
getBusinessData(businessId).entrancePickup = entrancePickup;
updateBusinessPickupLabelData(businessId);
}
setElementTransient(entrancePickup, false);
getBusinessData(businessId).entrancePickup = entrancePickup;
updateBusinessPickupLabelData(businessId);
} else {
let pickupModelId = getGameConfig().pickupModels[getGame()].Business;
if(businessData.entrancePickupModel != 0) {
pickupModelId = businessData.entrancePickupModel;
}
sendBusinessToPlayer(null, businessId, businessData.name, businessData.entrancePosition, blipModelId, pickupModelId, businessData.hasInterior, doesBusinessHaveAnyItemsToBuy(businessId));
}
return false;
@@ -1782,10 +1852,6 @@ function createBusinessEntrancePickup(businessId) {
*
*/
function createBusinessEntranceBlip(businessId) {
if(!areServerElementsSupported()) {
return false;
}
if(!getServerConfig().createBusinessBlips) {
return false;
}
@@ -1808,23 +1874,25 @@ function createBusinessEntranceBlip(businessId) {
logToConsole(LOG_VERBOSE, `[VRR.Job]: Creating entrance blip for business ${businessData.name} (model ${blipModelId})`);
let entranceBlip = createGameBlip(businessData.entrancePosition, blipModelId, getColourByType("businessBlue"));
if(entranceBlip != null) {
if(businessData.entranceDimension != -1) {
setElementDimension(entranceBlip, businessData.entranceDimension);
setElementOnAllDimensions(entranceBlip, false);
} else {
setElementOnAllDimensions(entranceBlip, true);
}
if(areServerElementsSupported()) {
let entranceBlip = createGameBlip(businessData.entrancePosition, blipModelId, 1, getColourByType("businessBlue"));
if(entranceBlip != null) {
if(businessData.entranceDimension != -1) {
setElementDimension(entranceBlip, businessData.entranceDimension);
setElementOnAllDimensions(entranceBlip, false);
} else {
setElementOnAllDimensions(entranceBlip, true);
}
if(getGlobalConfig().businessBlipStreamInDistance == -1 || getGlobalConfig().businessBlipStreamOutDistance == -1) {
entranceBlip.netFlags.distanceStreaming = false;
} else {
setElementStreamInDistance(entranceBlip, getGlobalConfig().businessBlipStreamInDistance);
setElementStreamOutDistance(entranceBlip, getGlobalConfig().businessBlipStreamOutDistance);
if(getGlobalConfig().businessBlipStreamInDistance == -1 || getGlobalConfig().businessBlipStreamOutDistance == -1) {
entranceBlip.netFlags.distanceStreaming = false;
} else {
setElementStreamInDistance(entranceBlip, getGlobalConfig().businessBlipStreamInDistance);
setElementStreamOutDistance(entranceBlip, getGlobalConfig().businessBlipStreamOutDistance);
}
setElementTransient(entranceBlip, false);
businessData.entranceBlip = entranceBlip;
}
setElementTransient(entranceBlip, false);
businessData.entranceBlip = entranceBlip;
}
}
@@ -1956,6 +2024,9 @@ function deleteBusiness(businessId, deletedBy = 0) {
let dbConnection = connectToDatabase();
let dbQuery = null;
deleteBusinessBlips(businessId);
deleteBusinessPickups(businessId);
if(dbConnection) {
dbQuery = queryDatabase(dbConnection, `DELETE FROM biz_main WHERE biz_id = ${tempBusinessData.databaseId}`);
if(dbQuery) {
@@ -1964,9 +2035,6 @@ function deleteBusiness(businessId, deletedBy = 0) {
disconnectFromDatabase(dbConnection);
}
deleteBusinessBlips(businessId);
deleteBusinessPickups(businessId);
removePlayersFromBusiness(businessId);
getServerData().businesses.splice(businessId, 1);
@@ -2508,10 +2576,19 @@ function cacheBusinessItems(businessId) {
clearArray(getBusinessData(businessId).floorItemCache);
clearArray(getBusinessData(businessId).storageItemCache);
let businessData = getBusinessData(businessId);
logToConsole(LOG_VERBOSE, `[VRR.Business] Caching business items for business ${businessId} (${businessData.name}) ...`);
getBusinessData(businessId).floorItemCache = getServerData().items.filter(item => item.ownerType == VRR_ITEM_OWNER_BIZFLOOR && item.ownerId == businessData.databaseId);
getBusinessData(businessId).storageItemCache = getServerData().items.filter(item => item.ownerType == VRR_ITEM_OWNER_BIZSTORAGE && item.ownerId == businessData.databaseId);
//let businessData = getBusinessData(businessId);
//logToConsole(LOG_VERBOSE, `[VRR.Business] Caching business items for business ${businessId} (${businessData.name}) ...`);
//getBusinessData(businessId).floorItemCache = getServerData().items.filter(item => item.ownerType == VRR_ITEM_OWNER_BIZFLOOR && item.ownerId == businessData.databaseId).map(i => i.index);
//getBusinessData(businessId).storageItemCache = getServerData().items.filter(item => item.ownerType == VRR_ITEM_OWNER_BIZSTORAGE && item.ownerId == businessData.databaseId);
logToConsole(LOG_VERBOSE, `[VRR.Business] Caching business items for business ${businessId} (${getBusinessData(businessId).name}) ...`);
for(let i in getServerData().items) {
if(getItemData(i).ownerType == VRR_ITEM_OWNER_BIZFLOOR && getItemData(i).ownerId == getBusinessData(businessId).databaseId) {
getBusinessData(businessId).floorItemCache.push(i);
} else if(getItemData(i).ownerType == VRR_ITEM_OWNER_BIZSTORAGE && getItemData(i).ownerId == getBusinessData(businessId).databaseId) {
getBusinessData(businessId).storageItemCache.push(i);
}
}
logToConsole(LOG_VERBOSE, `[VRR.Business] Successfully cached ${getBusinessData(businessId).floorItemCache.length} floor items and ${getBusinessData(businessId).storageItemCache} storage items for business ${businessId} (${getBusinessData(businessId).name})!`);
}

View File

@@ -38,7 +38,7 @@ function processPlayerChat(client, messageText) {
}
messageText = messageText.substring(0, 128);
messagePlayerNormal(null, `💬 ${getCharacterFullName(client)}: ${messageText}`);
messagePlayerNormal(null, `💬 ${getCharacterFullName(client)}: {MAINCOLOUR}${messageText}`, getPlayerColour(client));
messageDiscordChatChannel(`💬 ${getCharacterFullName(client)}: ${messageText}`);
} else {
messagePlayerNormal(null, `🛡️ (ADMIN) - ${messageText}`);

View File

@@ -142,7 +142,7 @@ function listClansCommand(command, params, client) {
let chunkedList = splitArrayIntoChunks(nameList, 5);
messagePlayerInfo(client, `{clanOrange}== {jobYellow}Clans {clanOrange}====================================`);
messagePlayerInfo(client, makeChatBoxSectionHeader(getLocaleString(client, "HeaderClansList")));
for(let i in chunkedList) {
messagePlayerInfo(client, chunkedList[i].join(", "));
@@ -169,7 +169,7 @@ function listClanRanksCommand(command, params, client) {
let chunkedList = splitArrayIntoChunks(rankNameList, 5);
messagePlayerInfo(client, `{clanOrange}== {jobYellow}Clan Ranks (${getClanData(clanId).name}) {clanOrange}=====================`);
messagePlayerInfo(client, makeChatBoxSectionHeader(getLocaleString(client, "HeaderClanRanksList")));
for(let i in chunkedList) {
messagePlayerInfo(client, chunkedList[i].join(", "));
@@ -191,7 +191,7 @@ function createClanCommand(command, params, client) {
// Create clan without owner. Can set owner with /clanowner afterward
createClan(params);
messageAdmins(`{ALTCOLOUR}${getPlayerName(client)} {MAINCOLOUR}created clan {clanOrange}${params}`);
messageAdmins(`{adminOrange}${getPlayerName(client)}{MAINCOLOUR} created clan {clanOrange}${params}`);
}
// ===========================================================================
@@ -209,7 +209,7 @@ function deleteClanCommand(command, params, client) {
return false;
}
messageAdmins(`{ALTCOLOUR}${getPlayerName(client)} {MAINCOLOUR}deleted clan {clanOrange}${getClanData(clanId).name}`);
messageAdmins(`{adminOrange}${getPlayerName(client)} {MAINCOLOUR}deleted clan {clanOrange}${getClanData(clanId).name}`);
deleteClan(clanId);
}
@@ -240,10 +240,13 @@ function setClanOwnerCommand(command, params, client) {
}
getClanData(clanId).owner = getPlayerCurrentSubAccount(targetClient).databaseId;
getClanData(clanId).needsSaved = true;
getPlayerCurrentSubAccount(targetClient).clan = getClanData(clanId).databaseId;
getPlayerCurrentSubAccount(targetClient).clanFlags = getClanFlagValue("All");
messageAdmins(`{ALTCOLOUR}${getPlayerName(client)} {MAINCOLOUR}set clan {clanOrange}${getClanData(clanId).name} {MAINCOLOUR}owner to {ALTCOLOUR}${getCharacterFullName(targetClient)}`);
//messageAdmins(`{adminOrange}${getPlayerName(client)} {MAINCOLOUR}set clan {clanOrange}${getClanData(clanId).name} {MAINCOLOUR}owner to {ALTCOLOUR}${getCharacterFullName(targetClient)}`);
messagePlayerSuccess(client, `You changed the clan owner to {ALTCOLOUR}${getCharacterFullName(targetClient)}`);
}
// ===========================================================================
@@ -266,9 +269,11 @@ function setClanTagCommand(command, params, client) {
return false;
}
getClanData(clanId).params = params;
getClanData(clanId).tag = params;
getClanData(clanId).needsSaved = true;
messageAdmins(`{ALTCOLOUR}${getPlayerName(client)} {MAINCOLOUR}set clan {clanOrange}${getClanData(clanId).index} {MAINCOLOUR}tag to {ALTCOLOUR}${params}`);
//messageAdmins(`{adminOrange}${getPlayerName(client)} {MAINCOLOUR}set clan {clanOrange}${getClanData(clanId).index} {MAINCOLOUR}tag to {ALTCOLOUR}${params}`);
messagePlayerSuccess(client, `You changed the clan tag to {ALTCOLOUR}${params}`);
}
// ===========================================================================
@@ -292,8 +297,10 @@ function setClanNameCommand(command, params, client) {
}
getClanData(clanId).name = params;
getClanData(clanId).needsSaved = true;
messageAdmins(`{ALTCOLOUR}${getPlayerName(client)} {MAINCOLOUR}set clan {clanOrange}${getClanData(clanId).index} {MAINCOLOUR}name to {ALTCOLOUR}${params}`);
//messageAdmins(`{adminOrange}${getPlayerName(client)} {MAINCOLOUR}set clan {clanOrange}${getClanData(clanId).index} {MAINCOLOUR}name to {ALTCOLOUR}${params}`);
messagePlayerSuccess(client, `You changed the clan name to {ALTCOLOUR}${params}`);
}
// ===========================================================================
@@ -354,8 +361,9 @@ function deleteClanRankCommand(command, params, client) {
}
removeClanRank(clanId, rankId);
getClanData(clanId).needsSaved = true;
messagePlayerSuccess(client, `You removed the {ALTCOLOUR}${tempRankName} {MAINCOLOUR}rank`);
messagePlayerSuccess(client, `You removed the {ALTCOLOUR}${tempRankName}{MAINCOLOUR} rank`);
}
// ===========================================================================
@@ -397,7 +405,7 @@ function setClanMemberTagCommand(command, params, client) {
}
}
getPlayerCurrentSubAccount(targetClient).ClanTag = getParam(params, " ", 2);
getPlayerCurrentSubAccount(targetClient).clanTag = getParam(params, " ", 2);
messagePlayerSuccess(client, `You set {ALTCOLOUR}${getCharacterFullName(targetClient)}'s {MAINCOLOUR}clan tag to {ALTCOLOUR}${getParam(params, " ", 2)}`);
messagePlayerAlert(client, `{ALTCOLOUR}${getCharacterFullName(targetClient)} {MAINCOLOUR}set your clan tag to {ALTCOLOUR}${getParam(params, " ", 2)}`);
@@ -431,7 +439,8 @@ function setClanRankTagCommand(command, params, client) {
}
}
getServerData().clans[clanId].rankId[rankId].customTag = newTag;
getClanRankData(clanId, rankId).customTag = newTag;
getClanRankData(clanId, rankId).needsSaved = true;
}
// ===========================================================================
@@ -479,7 +488,8 @@ function setClanRankLevelCommand(command, params, client) {
return false;
}
getServerData().clans[clanId].rankId[rankId].level = toInteger(newLevel);
getClanRankData(clanId, rankId).level = toInteger(newLevel);
getClanRankData(clanId, rankId).needsSaved = true;
}
// ===========================================================================
@@ -618,7 +628,8 @@ function addClanRankFlagCommand(command, params, client) {
let flagValue = getClanFlagValue(getParam(params, " ", 2));
addBitFlag(getClanRankData(clanId, rankId).flags, flagValue);
getClanRankData(clanId, rankId).flags = addBitFlag(getClanRankData(clanId, rankId).flags, flagValue);
getClanRankData(clanId, rankId).needsSaved = true;
messagePlayerSuccess(client, `You added the {ALTCOLOUR}${getParam(params, " ", 2)} {MAINCOLOUR}clan flag to rank {ALTCOLOUR}${getClanRankData(clanId, rankId).name}`);
}
@@ -656,7 +667,8 @@ function removeClanRankFlagCommand(command, params, client) {
let flagValue = getClanFlagValue(getParam(params, " ", 2));
removeBitFlag(getClanRankData(clanId, rankId).flags, flagValue);
getClanRankData(clanId, rankId).flags = removeBitFlag(getClanRankData(clanId, rankId).flags, flagValue);
getClanRankData(clanId, rankId).needsSaved = true;
messagePlayerSuccess(client, `You removed the {ALTCOLOUR}${getParam(params, " ", 2)} {MAINCOLOUR}clan flag from rank {ALTCOLOUR}${getClanRankData(clanId, rankId).name}`);
}
@@ -781,6 +793,7 @@ function setClanRankTitleCommand(command, params, client) {
let oldRankName = getClanRankData(clanId, rankId).name;
getClanRankData(clanId, rankId).name = getParam(params, " ", 2);
getClanRankData(clanId, rankId).needsSaved = true;
messagePlayerSuccess(client, `You changed the name of rank ${rankId} from {ALTCOLOUR}${oldRankName} {MAINCOLOUR}to {ALTCOLOUR}${params}`);
}

View File

@@ -135,6 +135,15 @@ class ServerConfigData {
sendChat: intToBool(dbAssoc["svr_discord_send_chat"]),
sendAdmin: intToBool(dbAssoc["svr_discord_send_admin"]),
};
this.economy = {
inflationMultiplier: toFloat(dbAssoc["svr_inflation_multiplier"]),
incomeTaxRate: toFloat(dbAssoc["svr_income_tax_rate"]),
passiveIncome: toFloat(dbAssoc["svr_passive_income"]),
}
this.devServer = intToBool(toInteger(server.getCVar("vrr_devserver")));
this.testerOnly = intToBool(toInteger(server.getCVar("vrr_testeronly")));
}
}
};
@@ -153,6 +162,7 @@ class ClientData {
this.connectTime = 0;
this.clientVersion = "0.0.0";
this.loginAttemptsRemaining = 3;
this.passwordResetAttemptsRemaining = 3;
this.afk = false;
this.jobRoute = -1;
@@ -918,21 +928,7 @@ class VehicleData {
this.colour4 = (vehicle) ? vehicle.colour4 : 1;
this.livery = 3;
this.extras = [
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
];
this.mods = [];
// Vehicle Attributes
this.locked = false;
@@ -955,6 +951,7 @@ class VehicleData {
this.needsSaved = false;
this.whoAdded = 0;
this.whenAdded = 0;
this.licensePlate = "";
this.interior = 0;
this.dimension = 0;
@@ -991,23 +988,6 @@ class VehicleData {
this.colour4 = toInteger(dbAssoc["veh_col4"]);
this.livery = toInteger(dbAssoc["veh_livery"]);
// Extras (components on SA, extras on IV+)
this.extras = [
toInteger(dbAssoc["veh_extra1"]),
toInteger(dbAssoc["veh_extra2"]),
toInteger(dbAssoc["veh_extra3"]),
toInteger(dbAssoc["veh_extra4"]),
toInteger(dbAssoc["veh_extra5"]),
toInteger(dbAssoc["veh_extra6"]),
toInteger(dbAssoc["veh_extra7"]),
toInteger(dbAssoc["veh_extra8"]),
toInteger(dbAssoc["veh_extra9"]),
toInteger(dbAssoc["veh_extra10"]),
toInteger(dbAssoc["veh_extra11"]),
toInteger(dbAssoc["veh_extra12"]),
toInteger(dbAssoc["veh_extra13"]),
];
// Vehicle Attributes
this.locked = intToBool(toInteger(dbAssoc["veh_locked"]));
this.engine = intToBool(toInteger(dbAssoc["veh_engine"]));
@@ -1024,6 +1004,7 @@ class VehicleData {
this.needsSaved = false;
this.whoAdded = toInteger(dbAssoc["veh_who_added"]);
this.whenAdded = toInteger(dbAssoc["veh_when_added"]);
this.licensePlate = toInteger(dbAssoc["veh_license_plate"]);
this.interior = toInteger(dbAssoc["veh_int"]);
this.dimension = toInteger(dbAssoc["veh_vw"]);
@@ -1475,9 +1456,7 @@ class NPCData {
constructor(dbAssoc = false) {
this.databaseId = 0;
this.serverId = 0;
this.firstName = "John";
this.lastName = "Doe";
this.middleName = "Q";
this.name = "NPC";
this.skin = 0;
this.cash = 0;
this.position = toVector3(0.0, 0.0, 0.0);
@@ -1496,12 +1475,15 @@ class NPCData {
this.fightStyle = 0;
this.health = 100;
this.armour = 100;
this.currentAction = VRR_NPCACTION_NONE;
this.currentAction = VRR_NPC_ACTION_NONE;
this.triggers = [];
this.typeFlags = 0;
this.heedThreats = false;
this.threats = 0;
this.invincible = false;
this.animationName = "";
this.ownerType = VRR_NPCOWNER_NONE;
this.ownerId = 0;
this.bodyParts = {
hair: [0,0],
@@ -1528,9 +1510,7 @@ class NPCData {
if(dbAssoc) {
this.databaseId = toInteger(dbAssoc["npc_id"]);
this.serverId = toInteger(dbAssoc["npc_server"]);
this.firstName = dbAssoc["npc_name_first"];
this.lastName = dbAssoc["npc_name_last"];
this.middleName = dbAssoc["npc_name_middle"] || "";
this.name = dbAssoc["npc_name"];
this.skin = toInteger(dbAssoc["npc_skin"]);
this.cash = toInteger(dbAssoc["npc_cash"]);
this.position = toVector3(toFloat(dbAssoc["npc_pos_x"]), toFloat(dbAssoc["npc_pos_y"]), toFloat(dbAssoc["npc_pos_z"]));
@@ -1551,6 +1531,7 @@ class NPCData {
this.heedThreats = intToBool(dbAssoc["npc_headthreats"]);
this.threats = toInteger(dbAssoc["npc_threats"]);
this.invincible = intToBool(dbAssoc["npc_invincible"]);
this.animationName = intToBool(dbAssoc["npc_animation"]);
this.bodyParts = {
hair: [toInteger(dbAssoc["npc_hd_part_hair_model"]) || 0, toInteger(dbAssoc["npc_hd_part_hair_texture"]) || 0],

View File

@@ -272,13 +272,6 @@ function sendJobRouteLocationToPlayer(client, position, colour) {
// ===========================================================================
function showPlayerChangePasswordGUI(client) {
logToConsole(LOG_DEBUG, `[VRR.Client] Sending change password GUI signal to ${getPlayerDisplayForConsole(client)}`);
sendNetworkEventToPlayer("vrr.changePassword", client);
}
// ===========================================================================
function showPlayerLoginSuccessGUI(client) {
logToConsole(LOG_DEBUG, `[VRR.Client] Sending login success GUI signal to ${getPlayerDisplayForConsole(client)}`);
sendNetworkEventToPlayer("vrr.loginSuccess", client);
@@ -344,18 +337,25 @@ function showPlayerNewCharacterGUI(client) {
function showPlayerChangePasswordGUI(client, errorMessage = "") {
logToConsole(LOG_DEBUG, `[VRR.Client] Sending show change password GUI signal to ${getPlayerDisplayForConsole(client)}`);
sendNetworkEventToPlayer("vrr.showChangePassword", client);
sendNetworkEventToPlayer("vrr.showChangePassword", client, errorMessage);
}
// ===========================================================================
function showPlayerResetPasswordCodeInputGUI(client) {
logToConsole(LOG_DEBUG, `[VRR.Client] Sending show reset password GUI signal to ${getPlayerDisplayForConsole(client)}`);
logToConsole(LOG_DEBUG, `[VRR.Client] Sending show reset password code input GUI signal to ${getPlayerDisplayForConsole(client)}`);
sendNetworkEventToPlayer("vrr.showResetPasswordCodeInput", client);
}
// ===========================================================================
function showPlayerResetPasswordEmailInputGUI(client) {
logToConsole(LOG_DEBUG, `[VRR.Client] Sending show reset password email input GUI signal to ${getPlayerDisplayForConsole(client)}`);
sendNetworkEventToPlayer("vrr.showResetPasswordEmailInput", client);
}
// ===========================================================================
function showPlayerCharacterSelectGUI(client, firstName, lastName, cash, clan, lastPlayed, skin) {
logToConsole(LOG_DEBUG, `[VRR.Client] Sending character select GUI signal to ${getPlayerDisplayForConsole(client)}`);
sendNetworkEventToPlayer("vrr.showCharacterSelect", client, firstName, lastName, cash, clan, lastPlayed, skin);
@@ -400,7 +400,7 @@ function showPlayerInfoGUI(client, infoMessage, infoTitle, buttonText = "OK") {
function showPlayerErrorGUI(client, errorMessage, errorTitle, buttonText = "OK") {
logToConsole(LOG_DEBUG, `[VRR.Client] Sending show error GUI signal to ${getPlayerDisplayForConsole(client)} (Title: ${errorTitle}, Message: ${errorMessage})`);
sendNetworkEventToPlayer("vrr.showInfo", client, errorMessage, errorTitle, buttonText);
sendNetworkEventToPlayer("vrr.showError", client, errorMessage, errorTitle, buttonText);
}
// ===========================================================================
@@ -990,21 +990,21 @@ function sendPlayerEnterPropertyKey(client, key) {
function makePedPlayAnimation(ped, animationSlot, positionOffset) {
setEntityData(ped, "vrr.anim", animationSlot, true);
sendNetworkEventToPlayer("vrr.pedAnim", null, getPedForNetworkEvent(ped), animationSlot, positionOffset);
sendNetworkEventToPlayer("vrr.anim", null, getPedForNetworkEvent(ped), animationSlot, positionOffset);
}
// ===========================================================================
function makePedStopAnimation(ped) {
removeEntityData(ped, "vrr.anim");
sendNetworkEventToPlayer("vrr.pedStopAnim", null, getPedForNetworkEvent(ped));
sendNetworkEventToPlayer("vrr.stopAnim", null, getPedForNetworkEvent(ped));
}
// ===========================================================================
function forcePedAnimation(ped, animationSlot, positionOffset = 0) {
addEntityData(ped, "vrr.anim", animationSlot, true);
sendNetworkEventToPlayer("vrr.forcePedAnim", null, getPedForNetworkEvent(ped), animationSlot, positionOffset);
sendNetworkEventToPlayer("vrr.forceAnim", null, getPedForNetworkEvent(ped), animationSlot, positionOffset);
}
// ===========================================================================
@@ -1094,8 +1094,8 @@ function sendBusinessToPlayer(client, businessId, name, entrancePosition, blipMo
// ==========================================================================
function sendHouseToPlayer(client, houseId, entrancePosition, blipModel, pickupModel, hasInterior) {
sendNetworkEventToPlayer("vrr.house", client, houseId, entrancePosition, blipModel, pickupModel, hasInterior);
function sendHouseToPlayer(client, houseId, description, entrancePosition, blipModel, pickupModel, hasInterior) {
sendNetworkEventToPlayer("vrr.house", client, houseId, description, entrancePosition, blipModel, pickupModel, hasInterior);
}
// ==========================================================================

View File

@@ -411,8 +411,10 @@ function loadCommands() {
npc: [
new CommandData("addnpc", createNPCCommand, "<skin id/name>", getStaffFlagValue("ManageNPCs"), true, false, "Creates an NPC with the specified skin"),
new CommandData("delnpc", deleteNPCCommand, "", getStaffFlagValue("ManageNPCs"), true, false, "Deletes the nearest NPC"),
//new CommandData("npcinfo", getNPCInfoCommand, "", getStaffFlagValue("ManageNPCs"), true, false, "Shows info about the nearest NPC"),
new CommandData("npcinfo", getNPCInfoCommand, "", getStaffFlagValue("ManageNPCs"), true, false, "Shows info about the nearest NPC"),
new CommandData("npcanim", setNPCAnimationCommand, "<animation name>", getStaffFlagValue("ManageNPCs"), true, false, "Plays the specified animation on the nearest NPC"),
new CommandData("npcname", setNPCNameCommand, "<name>", getStaffFlagValue("ManageNPCs"), true, false, "Sets the name of the nearest NPC"),
new CommandData("npclookatplr", toggleNPCLookAtClosestPlayerCommand, "<name>", getStaffFlagValue("ManageNPCs"), true, false, "Makes the NPC look at the closest player"),
//new CommandData("npcrespawnall", respawnAllNPCsCommand, "", getStaffFlagValue("ManageNPCs"), true, false, "Respawns all NPCs"),
//new CommandData("npcrespawn", respawnNPCCommand, "", getStaffFlagValue("ManageNPCs"), true, false, "Respawns the nearest NPC"),
],
@@ -465,12 +467,12 @@ function loadCommands() {
new CommandData("dn", teleportDownCommand, "[distance in meters]", getStaffFlagValue("BasicModeration"), true, true, "Teleports you downward a certain distance in meters."),
new CommandData("int", playerInteriorCommand, "<player name/id> [interior id]", getStaffFlagValue("BasicModeration"), true, true, "Gets or sets a player's game interior."),
new CommandData("vw", playerVirtualWorldCommand, "<player name/id> [virtual world id]", getStaffFlagValue("BasicModeration"), true, true, "Gets or sets a player's virtual world/dimension."),
new CommandData("addstaffflag", addPlayerStaffFlagCommand, "<player name/id> <flag name>", getStaffFlagValue("ManageAdmins"), true, true, "Gives a player a staff flag by name (this server only)."),
new CommandData("delstaffflag", removePlayerStaffFlagCommand, "<player name/id> <flag name>", getStaffFlagValue("ManageAdmins"), true, true, "Takes a player's staff flag by name (this server only)."),
new CommandData("getstaffflags", getPlayerStaffFlagsCommand, "<player name/id>", getStaffFlagValue("ManageAdmins"), true, true, "Shows a list of all staff flags a player has (this server only)."),
new CommandData("addplrstaffflag", addPlayerStaffFlagCommand, "<player name/id> <flag name>", getStaffFlagValue("ManageAdmins"), true, true, "Gives a player a staff flag by name (this server only)."),
new CommandData("delplrstaffflag", removePlayerStaffFlagCommand, "<player name/id> <flag name>", getStaffFlagValue("ManageAdmins"), true, true, "Takes a player's staff flag by name (this server only)."),
new CommandData("plrstaffflags", getPlayerStaffFlagsCommand, "<player name/id>", getStaffFlagValue("ManageAdmins"), true, true, "Shows a list of all staff flags a player has (this server only)."),
new CommandData("clearstaffflags", removePlayerStaffFlagsCommand, "<player name/id>", getStaffFlagValue("ManageAdmins"), true, true, "Removes all staff flags for a player (this server only)."),
new CommandData("staffflags", getStaffFlagsCommand, "", getStaffFlagValue("ManageAdmins"), true, true, "Shows a list of all valid staff flag names."),
new CommandData("stafftitle", setPlayerStaffTitleCommand, "", getStaffFlagValue("ManageAdmins"), true, true, "Sets a player's staff title."),
new CommandData("allstaffflags", getStaffFlagsCommand, "", getStaffFlagValue("ManageAdmins"), true, true, "Shows a list of all valid staff flag names."),
new CommandData("plrstafftitle", setPlayerStaffTitleCommand, "", getStaffFlagValue("ManageAdmins"), true, true, "Sets a player's staff title."),
new CommandData("givemoney", givePlayerMoneyCommand, "<player name/id> <amount>", getStaffFlagValue("serverManager"), true, true),
new CommandData("nonrpname", forceCharacterNameChangeCommand, "<player name/id>", getStaffFlagValue("BasicModeration"), true, true, "Forces a player to change their current character's name."),
new CommandData("setname", setCharacterNameCommand, "<player name/id> <first name> <last name>", getStaffFlagValue("BasicModeration"), true, true, "Changes a character's name directly."),
@@ -523,6 +525,8 @@ function loadCommands() {
utilities: [],
vehicle: [
new CommandData("addveh", createVehicleCommand, "<model id/name>", getStaffFlagValue("ManageVehicles"), true, false),
//new CommandData("spawnveh", createVehicleCommand, "<model id/name>", getStaffFlagValue("ManageVehicles"), true, false),
//new CommandData("createveh", createVehicleCommand, "<model id/name>", getStaffFlagValue("ManageVehicles"), true, false),
new CommandData("tempveh", createTemporaryVehicleCommand, "<model id/name>", getStaffFlagValue("ManageVehicles"), true, false),
new CommandData("delveh", deleteVehicleCommand, "", getStaffFlagValue("ManageVehicles"), true, false),
new CommandData("nearveh", getNearbyVehiclesCommand, "", getStaffFlagValue("None"), true, false),
@@ -543,9 +547,13 @@ function loadCommands() {
new CommandData("vehjob", setVehicleJobCommand, "[job id/name]", getStaffFlagValue("ManageVehicles"), true, true),
new CommandData("vehdelowner", removeVehicleOwnerCommand, "", getStaffFlagValue("ManageVehicles"), true, true),
new CommandData("vehrank", setVehicleRankCommand, "<rank id/name>", getStaffFlagValue("None"), true, true),
new CommandData("vehiclerank", setVehicleRankCommand, "<rank id/name>", getStaffFlagValue("None"), true, true),
new CommandData("vehinfo", getVehicleInfoCommand, "", getStaffFlagValue("None"), true, true),
new CommandData("vehicleinfo", getVehicleInfoCommand, "", getStaffFlagValue("None"), true, true),
new CommandData("vehpark", toggleVehicleSpawnLockCommand, "", getStaffFlagValue("ManageVehicles"), true, true),
new CommandData("parkveh", toggleVehicleSpawnLockCommand, "", getStaffFlagValue("ManageVehicles"), true, true),
new CommandData("vehiclepark", toggleVehicleSpawnLockCommand, "", getStaffFlagValue("ManageVehicles"), true, true),
new CommandData("parkvehicle", toggleVehicleSpawnLockCommand, "", getStaffFlagValue("ManageVehicles"), true, true),
new CommandData("vehrespawnall", respawnAllVehiclesCommand, "", getStaffFlagValue("ManageVehicles"), true, true, "Respawns all vehicles (also respawns all traffic vehicles)"),
new CommandData("vehrespawnempty", respawnEmptyVehiclesCommand, "", getStaffFlagValue("ManageVehicles"), true, true, "Respawns all empty/unoccupied vehicles"),
new CommandData("vehrespawnjob", respawnJobVehiclesCommand, "", getStaffFlagValue("ManageVehicles"), true, true, "Respawns all job vehicles"),
@@ -555,7 +563,6 @@ function loadCommands() {
new CommandData("vehrespawnbiz", respawnBusinessVehiclesCommand, "", getStaffFlagValue("ManageVehicles"), true, true, "Respawns all business-owned vehicles"),
new CommandData("vehrespawn", respawnVehicleCommand, "", getStaffFlagValue("ManageVehicles"), true, true, "Respawns your current vehicle"),
new CommandData("vehreloadall", reloadAllVehiclesCommand, "", getStaffFlagValue("ManageVehicles"), true, true, "Deletes and reloads all vehicles from database"),
new CommandData("carrespawnall", respawnAllVehiclesCommand, "", getStaffFlagValue("ManageVehicles"), true, true, "Respawns all vehicles (also respawns all traffic vehicles)"),
new CommandData("carrespawnempty", respawnEmptyVehiclesCommand, "", getStaffFlagValue("ManageVehicles"), true, true, "Respawns all empty/unoccupied vehicles"),
new CommandData("carrespawnjob", respawnJobVehiclesCommand, "", getStaffFlagValue("ManageVehicles"), true, true, "Respawns all job vehicles"),
@@ -565,15 +572,34 @@ function loadCommands() {
new CommandData("carrespawnbiz", respawnBusinessVehiclesCommand, "", getStaffFlagValue("ManageVehicles"), true, true, "Respawns all business-owned vehicles"),
new CommandData("carrespawn", respawnVehicleCommand, "", getStaffFlagValue("ManageVehicles"), true, true, "Respawns your current vehicle"),
new CommandData("carreloadall", reloadAllVehiclesCommand, "", getStaffFlagValue("ManageVehicles"), true, true, "Deletes and reloads all vehicles from database"),
new CommandData("vehrent", rentVehicleCommand, "", getStaffFlagValue("None"), true, true, "Starts renting your current vehicle (if rentable)"),
new CommandData("rentveh", rentVehicleCommand, "", getStaffFlagValue("None"), true, true, "Starts renting your current vehicle (if rentable)"),
new CommandData("vehiclerent", rentVehicleCommand, "", getStaffFlagValue("None"), true, true, "Starts renting your current vehicle (if rentable)"),
new CommandData("rentvehicle", rentVehicleCommand, "", getStaffFlagValue("None"), true, true, "Starts renting your current vehicle (if rentable)"),
new CommandData("vehrentprice", setVehicleRentPriceCommand, "", getStaffFlagValue("None"), true, true, "Sets your vehicle's rent price"),
new CommandData("vehbuyprice", setVehicleBuyPriceCommand, "", getStaffFlagValue("None"), true, true, "Sets your vehicle's rent price"),
new CommandData("vehiclebuyprice", setVehicleBuyPriceCommand, "", getStaffFlagValue("None"), true, true, "Sets your vehicle's rent price"),
new CommandData("vehprice", setVehicleBuyPriceCommand, "", getStaffFlagValue("None"), true, true, "Sets your vehicle's rent price"),
new CommandData("vehicleprice", setVehicleBuyPriceCommand, "", getStaffFlagValue("None"), true, true, "Sets your vehicle's rent price"),
new CommandData("rentpriceveh", setVehicleRentPriceCommand, "", getStaffFlagValue("None"), true, true, "Sets your vehicle's rent price"),
new CommandData("buypriceveh", setVehicleBuyPriceCommand, "", getStaffFlagValue("None"), true, true, "Sets your vehicle's rent price"),
new CommandData("stoprentveh", stopRentingVehicleCommand, "", getStaffFlagValue("None"), true, true, "Stops renting your vehicle"),
new CommandData("vehstoprent", stopRentingVehicleCommand, "", getStaffFlagValue("None"), true, true, "Stops renting your vehicle"),
new CommandData("vehiclerentprice", setVehicleRentPriceCommand, "", getStaffFlagValue("None"), true, true, "Sets your vehicle's rent price"),
new CommandData("vehiclestoprent", stopRentingVehicleCommand, "", getStaffFlagValue("None"), true, true, "Stops renting your vehicle"),
new CommandData("vehbuy", buyVehicleCommand, "", getStaffFlagValue("None"), true, true, "Purchases your vehicle"),
new CommandData("vehiclebuy", buyVehicleCommand, "", getStaffFlagValue("None"), true, true, "Purchases your vehicle"),
new CommandData("buyveh", buyVehicleCommand, "", getStaffFlagValue("None"), true, true, "Purchases your vehicle"),
new CommandData("buyvehicle", buyVehicleCommand, "", getStaffFlagValue("None"), true, true, "Purchases your vehicle"),
new CommandData("vehcolour", vehicleAdminColourCommand, "<colour1> <colour2>", getStaffFlagValue("None"), true, true, "Sets a vehicle's colour"),
new CommandData("vehiclecolour", vehicleAdminColourCommand, "<colour1> <colour2>", getStaffFlagValue("None"), true, true, "Sets a vehicle's colour"),
new CommandData("vehlivery", vehicleAdminLiveryCommand, "<livery id>", getStaffFlagValue("None"), true, true, "Sets your vehicle's livery/paintjob"),
new CommandData("vehiclelivery", vehicleAdminLiveryCommand, "<livery id>", getStaffFlagValue("None"), true, true, "Sets your vehicle's livery/paintjob"),
new CommandData("vehrepair", vehicleAdminRepairCommand, "", getStaffFlagValue("None"), true, true, "Repairs your vehicle"),
new CommandData("vehiclerepair", vehicleAdminRepairCommand, "", getStaffFlagValue("None"), true, true, "Repairs your vehicle"),
new CommandData("repairveh", vehicleAdminRepairCommand, "", getStaffFlagValue("None"), true, true, "Repairs your vehicle"),
new CommandData("repairvehicle", vehicleAdminRepairCommand, "", getStaffFlagValue("None"), true, true, "Repairs your vehicle"),
new CommandData("passenger", enterVehicleAsPassengerCommand, "", getStaffFlagValue("None"), true, true, "Enters a vehicle as passenger"),
],
};
@@ -799,7 +825,7 @@ function processPlayerCommand(command, params, client) {
if(!isConsole(client)) {
if(!doesPlayerHaveStaffPermission(client, getCommandRequiredPermissions(toLowerCase(command)))) {
logToConsole(LOG_WARN, `[VRR.Command] ${getPlayerDisplayForConsole(client)} attempted to use command, but failed (no permission): /${command} ${paramsDisplay}`);
messagePlayerError(client, "CommandNoPermissions", `{ALTCOLOUR}/${toLowerCase(command)}{MAINCOLOUR}`);
messagePlayerError(client, getLocaleString(client, "CommandNoPermissions", `{ALTCOLOUR}/${toLowerCase(command)}{MAINCOLOUR}`));
return false;
}
}

View File

@@ -201,9 +201,6 @@ function loadServerConfigFromId(tempServerId) {
function applyConfigToServer(tempServerConfig) {
logToConsole(LOG_INFO, "[VRR.Config]: Applying server config ...");
getServerConfig().devServer = intToBool(toInteger(server.getCVar("vrr_devserver")));
getServerConfig().testerOnly = intToBool(toInteger(server.getCVar("vrr_testeronly")));
logToConsole(LOG_DEBUG, "[VRR.Config]: Server config applied successfully!");
if(isTimeSupported()) {

View File

@@ -308,6 +308,7 @@ const VRR_2FA_STATE_SETUP_CODEFROMAPP = 3; // Waiting on player to enter c
const VRR_RESETPASS_STATE_NONE = 0; // None
const VRR_RESETPASS_STATE_CODEINPUT = 1; // Waiting on player to enter code sent via email
const VRR_RESETPASS_STATE_SETPASS = 2; // Waiting on player to enter new password
const VRR_RESETPASS_STATE_EMAILCONFIRM = 3; // Waiting on player to enter their email to confirm it's correct
// NPC Trigger Condition Match Types
const VRR_NPC_COND_MATCH_NONE = 0; // None (invalid)
@@ -358,4 +359,13 @@ const VRR_GPS_TYPE_GAMELOC = 5; // Game Location
// Discord Webhook Types
const VRR_DISCORD_WEBHOOK_NONE = 0;
const VRR_DISCORD_WEBHOOK_LOG = 1;
const VRR_DISCORD_WEBHOOK_ADMIN = 2;
const VRR_DISCORD_WEBHOOK_ADMIN = 2;
// NPC Owner Types
const VRR_NPCOWNER_NONE = 0; // Not owned
const VRR_NPCOWNER_PLAYER = 1; // Owned by a player (character/subaccount)
const VRR_NPCOWNER_JOB = 2; // Owned by a job
const VRR_NPCOWNER_CLAN = 3; // Owned by a clan
const VRR_NPCOWNER_FACTION = 4; // Owned by a faction (not used at the moment)
const VRR_NPCOWNER_PUBLIC = 5; // Public NPC. Anybody can do stuff with it.
const VRR_NPCOWNER_BIZ = 6; // Owned by a business

View File

@@ -41,7 +41,7 @@ function playerPayDay(client) {
grossIncome = grossIncome*2;
}
let incomeTaxAmount = calculateIncomeTax(wealth);
let incomeTaxAmount = Math.round(calculateIncomeTax(wealth));
let netIncome = grossIncome-incomeTaxAmount;

View File

@@ -15,7 +15,35 @@ function initEventScript() {
// ===========================================================================
function onInitialConnectionToServer(ipAddress, port) {
function addAllEventHandlers() {
addEventHandler("onResourceStart", onResourceStart);
addEventHandler("onResourceStop", onResourceStop);
addEventHandler("onServerStop", onResourceStop);
addEventHandler("onProcess", onProcess);
addEventHandler("onEntityProcess", onEntityProcess);
addEventHandler("onPlayerConnect", onPlayerConnect);
addEventHandler("onPlayerJoin", onPlayerJoin);
addEventHandler("onPlayerJoined", onPlayerJoined);
addEventHandler("onPlayerChat", onPlayerChat);
addEventHandler("onPlayerQuit", onPlayerQuit);
addEventHandler("onElementStreamIn", onElementStreamIn);
addEventHandler("onElementStreamOut", onElementStreamOut);
addEventHandler("onPedSpawn", onPedSpawn);
addEventHandler("onPedEnterVehicle", onPedEnteringVehicle);
addEventHandler("onPedExitVehicle", onPedExitingVehicle);
addEventHandler("onPedEnteringVehicle", onPedEnteringVehicle);
addEventHandler("onPedExitingVehicle", onPedExitingVehicle);
//addEventHandler("OnPlayerCommand", onPlayerCommand);
}
// ===========================================================================
function onPlayerConnect(event, ipAddress, port) {
logToConsole(LOG_INFO, `[VRR.Event] Client connecting (IP: ${ipAddress})`);
//if(isIpAddressBanned(ipAddress)) {
// messagePlayerError(client, "You are banned from this server!");
@@ -25,13 +53,17 @@ function onInitialConnectionToServer(ipAddress, port) {
// ===========================================================================
function onPlayerJoin(client) {
function onPlayerJoin(event, client) {
logToConsole(LOG_INFO, `[VRR.Event] Client ${getPlayerName(client)}[${getPlayerId(client)}] joining from ${getPlayerIP(client)}`);
if(isFadeCameraSupported()) {
fadeCamera(client, true, 1.0);
}
//if(isCustomCameraSupported()) {
// showConnectCameraToPlayer(client);
//}
let messageText = `👋 ${getPlayerName(client)} is connecting to the server ...`;
messageDiscordEventChannel(messageText);
@@ -45,13 +77,13 @@ function onPlayerJoin(client) {
// ===========================================================================
function onPlayerJoined(client) {
function onPlayerJoined(event, client) {
}
// ===========================================================================
function onElementStreamIn(element, client) {
function onElementStreamIn(event, element, client) {
//if(getPlayerDimension(client) != getElementDimension(element)) {
// event.preventDefault();
//}
@@ -66,13 +98,13 @@ function onElementStreamIn(element, client) {
// ===========================================================================
function onElementStreamOut(element, client) {
function onElementStreamOut(event, element, client) {
}
// ===========================================================================
function onPlayerQuit(client, quitReasonId) {
function onPlayerQuit(event, client, quitReasonId) {
logToConsole(LOG_INFO, `👋 Client ${getPlayerDisplayForConsole(client)} disconnected (${disconnectReasons[quitReasonId]}[${quitReasonId}])`);
updateConnectionLogOnQuit(client, quitReasonId);
@@ -94,21 +126,18 @@ function onPlayerQuit(client, quitReasonId) {
resetClientStuff(client);
getServerData().clients[getPlayerId(client)] = null;
}
clearTemporaryVehicles();
clearTemporaryPeds();
}
// ===========================================================================
async function onPlayerChat(client, messageText) {
async function onPlayerChat(event, client, messageText) {
processPlayerChat(client, messageText);
event.preventDefault();
}
// ===========================================================================
function onProcess(deltaTime = 0) {
function onProcess(event, deltaTime) {
updateServerGameTime();
//checkPlayerSpawning();
//checkPlayerPedState();
@@ -119,12 +148,12 @@ function onProcess(deltaTime = 0) {
// ===========================================================================
function onEntityProcess(entity) {
function onEntityProcess(event, entity) {
}
// ===========================================================================
function onPedEnteringVehicle(ped, vehicle, seat) {
function onPedEnteringVehicle(event, ped, vehicle, seat) {
if(ped.isType(ELEMENT_PLAYER)) {
let client = getClientFromPlayerElement(ped);
getPlayerData(client).pedState = VRR_PEDSTATE_ENTERINGVEHICLE;
@@ -155,7 +184,7 @@ function onPedEnteringVehicle(ped, vehicle, seat) {
// ===========================================================================
function onPedExitingVehicle(ped, vehicle) {
function onPedExitingVehicle(event, ped, vehicle) {
if(!getVehicleData(vehicle)) {
return false;
}
@@ -174,22 +203,22 @@ function onPedExitingVehicle(ped, vehicle) {
// ===========================================================================
function onResourceStart(resource) {
function onResourceStart(event, resource) {
logToConsole(LOG_WARN, `[VRR.Event] Resource ${resource.name} started!`);
if(resource != thisResource) {
messageAdmins(`{MAINCOLOUR}Resource {ALTCOLOUR}${resource.name}{MAINCOLOUR} started!`);
}
//if(resource != thisResource) {
// messageAdmins(`{MAINCOLOUR}Resource {ALTCOLOUR}${resource.name}{MAINCOLOUR} started!`);
//}
}
// ===========================================================================
function onResourceStop(resource) {
function onResourceStop(event, resource) {
logToConsole(LOG_WARN, `[VRR.Event] Resource ${resource.name} stopped!`);
if(resource != thisResource) {
messageAdmins(`{MAINCOLOUR}Resource {ALTCOLOUR}${resource.name}{MAINCOLOUR} stopped!`);
}
//if(resource != thisResource) {
// messageAdmins(`{MAINCOLOUR}Resource {ALTCOLOUR}${resource.name}{MAINCOLOUR} stopped!`);
//}
if(resource == thisResource) {
kickAllClients();
@@ -497,9 +526,6 @@ function onPlayerSpawn(client) {
//messagePlayerNormal(client, "This server is in early development and may restart at any time for updates.", getColourByName("orange"));
//messagePlayerNormal(client, "Please report any bugs using /bug and suggestions using /idea", getColourByName("yellow"));
logToConsole(LOG_DEBUG, `[VRR.Event] Updating spawned state for ${getPlayerDisplayForConsole(client)} to true`);
updatePlayerSpawnedState(client, true);
logToConsole(LOG_DEBUG, `[VRR.Event] Setting player interior for ${getPlayerDisplayForConsole(client)} to ${getPlayerCurrentSubAccount(client).interior}`);
setPlayerInterior(client, getPlayerCurrentSubAccount(client).interior);
@@ -599,12 +625,30 @@ function onPlayerSpawn(client) {
sendAllHousesToPlayer(client);
sendAllJobsToPlayer(client);
//sendAllVehiclesToPlayer(client);
requestPlayerPedNetworkId(client);
}
logToConsole(LOG_DEBUG, `[VRR.Event] Updating spawned state for ${getPlayerDisplayForConsole(client)} to true`);
updatePlayerSpawnedState(client, true);
getPlayerData(client).payDayTickStart = sdl.ticks;
// Stop playing intro music and any other radio
stopRadioStreamForPlayer(client);
// Start playing business/house radio if in one
let businessId = getPlayerBusiness(client);
let houseId = getPlayerHouse(client);
if(businessId != -1) {
if(getBusinessData(businessId).streamingRadioStation != -1) {
playRadioStreamForPlayer(client, getRadioStationData(getBusinessData(businessId).streamingRadioStation).url, true, getPlayerStreamingRadioVolume(client), null);
}
} else if(houseId != -1) {
if(getHouseData(houseId).streamingRadioStation != -1) {
playRadioStreamForPlayer(client, getRadioStationData(getHouseData(houseId).streamingRadioStation).url, true, getPlayerStreamingRadioVolume(client), null);
}
}
messageDiscordEventChannel(`🧍 ${getPlayerName(client)} spawned as ${getCharacterFullName(client)}`);
}

View File

@@ -189,7 +189,8 @@ function playerPromptAnswerYes(client) {
getHouseData(houseId).needsSaved = true;
updateHousePickupLabelData(houseId);
messagePlayerSuccess(client, `You are now the owner of {houseGreen}${getHouseData(houseId).description}`);
messageDiscordEventChannel(`🏘️ ${getCharacterFullName(client)} is now the owner of *${getHouseData(houseId).description}*!`);
messagePlayerSuccess(client, `🏘️ You are now the owner of {houseGreen}${getHouseData(houseId).description}`);
break;
}
@@ -206,7 +207,7 @@ function playerPromptAnswerYes(client) {
}
if(getPlayerCurrentSubAccount(client).cash < getBusinessData(businessId).buyPrice) {
messagePlayerError(client, getLocaleString(client, "HousePurchaseNotEnoughMoney"));
messagePlayerError(client, getLocaleString(client, "BusinessPurchaseNotEnoughMoney"));
return false;
}
@@ -216,7 +217,8 @@ function playerPromptAnswerYes(client) {
getBusinessData(businessId).needsSaved = true;
updateBusinessPickupLabelData(businessId);
messagePlayerSuccess(client, `You are now the owner of {businessBlue}${getBusinessData(businessId).name}`);
messageDiscordEventChannel(`🏢 ${getCharacterFullName(client)} is now the owner of *${getBusinessData(businessId).name}*!`);
messagePlayerSuccess(client, `🏢 You are now the owner of {businessBlue}${getBusinessData(businessId).name}`);
break;
}
@@ -255,12 +257,6 @@ function playerToggledGUI(client) {
// ===========================================================================
function showPlayerChangePasswordGUI(client) {
sendNetworkEventToPlayer("vrr.changePassword", client);
}
// ===========================================================================
function showPlayerTwoFactorAuthenticationGUI(client) {
sendNetworkEventToPlayer("vrr.2fa", client);
}

View File

@@ -841,10 +841,6 @@ function createAllHouseBlips() {
// ===========================================================================
function createHouseEntrancePickup(houseId) {
if(!areServerElementsSupported()) {
return false;
}
if(!getServerConfig().createHousePickups) {
return false;
}
@@ -869,16 +865,25 @@ function createHouseEntrancePickup(houseId) {
pickupModelId = getHouseData(houseId).entrancePickupModel;
}
let entrancePickup = createGamePickup(pickupModelId, getHouseData(houseId).entrancePosition, getGameConfig().pickupTypes[getGame()].house);
if(entrancePickup != null) {
setElementOnAllDimensions(entrancePickup, false);
setElementDimension(entrancePickup, getHouseData(houseId).entranceDimension);
setElementStreamInDistance(entrancePickup, getGlobalConfig().housePickupStreamInDistance);
setElementStreamOutDistance(entrancePickup, getGlobalConfig().housePickupStreamOutDistance);
setElementTransient(entrancePickup, false);
if(areServerElementsSupported()) {
let entrancePickup = createGamePickup(pickupModelId, getHouseData(houseId).entrancePosition, getGameConfig().pickupTypes[getGame()].house);
if(entrancePickup != null) {
setElementOnAllDimensions(entrancePickup, false);
setElementDimension(entrancePickup, getHouseData(houseId).entranceDimension);
setElementStreamInDistance(entrancePickup, getGlobalConfig().housePickupStreamInDistance);
setElementStreamOutDistance(entrancePickup, getGlobalConfig().housePickupStreamOutDistance);
setElementTransient(entrancePickup, false);
getHouseData(houseId).entrancePickup = entrancePickup;
updateHousePickupLabelData(houseId);
getHouseData(houseId).entrancePickup = entrancePickup;
updateHousePickupLabelData(houseId);
}
} else {
let pickupModelId = getGameConfig().pickupModels[getGame()].House;
if(houseData.entrancePickupModel != 0) {
pickupModelId = houseData.entrancePickupModel;
}
sendHouseToPlayer(null, houseId, houseId.description, houseId.entrancePosition, blipModelId, pickupModelId, houseId.hasInterior);
}
}
@@ -912,7 +917,7 @@ function createHouseEntranceBlip(houseId) {
blipModelId = getHouseData(houseId).entranceBlipModel;
}
let entranceBlip = createGameBlip(houseData.entrancePosition, blipModelId, getColourByName("houseGreen"));
let entranceBlip = createGameBlip(houseData.entrancePosition, blipModelId, 1, getColourByName("houseGreen"));
if(entranceBlip != null) {
if(houseData.exitDimension != -1) {
setElementDimension(entranceBlip, houseData.entranceDimension);

View File

@@ -862,6 +862,8 @@ function playerUseItem(client, hotBarSlot) {
if(getItemData(itemIndex).value <= 0) {
destroyItem(itemIndex);
}
} else {
messagePlayerError(client, getLocaleString(client, "VehicleRepairFailedTooFar"));
}
break;
}
@@ -1374,8 +1376,11 @@ function setAllItemTypeDataIndexes() {
function cacheAllGroundItems() {
clearArray(getServerData().groundItemCache);
getServerData().groundItemCache = getServerData().items.filter(item => item.ownerType == VRR_ITEM_OWNER_GROUND);
//getServerData().groundPlantCache = getServerData().items.filter(item => item.ownerType == VRR_ITEM_OWNER_PLANT);
for(let i in getServerData().items) {
if(getServerData().items[i].ownerType == VRR_ITEM_OWNER_GROUND) {
getServerData().groundItemCache.push(i);
}
}
}
// ===========================================================================
@@ -1411,11 +1416,19 @@ function cachePlayerHotBarItems(client) {
return false;
}
clearArray(getPlayerData(client).hotBarItems);
getPlayerData(client).hotBarItems = getServerData().items.filter(item => item.ownerType == VRR_ITEM_OWNER_PLAYER && item.ownerId == getPlayerCurrentSubAccount(client).databaseId);
for(let i = 0 ; i < 9 ; i++) {
getPlayerData(client).hotBarItems[i] = -1;
}
if(getPlayerData(client).hotBarItems.length < getGlobalConfig().maxPlayerItemSlots) {
getPlayerData(client).hotBarItems.concat(Array(getGlobalConfig().maxPlayerItemSlots-getPlayerData(client).hotBarItems.length).fill(-1));
for(let i in getServerData().items) {
if(getItemData(i).ownerType == VRR_ITEM_OWNER_PLAYER) {
if(getItemData(i).ownerId == getPlayerCurrentSubAccount(client).databaseId) {
let firstSlot = getPlayerFirstEmptyHotBarSlot(client);
if(firstSlot != -1) {
getPlayerData(client).hotBarItems[firstSlot] = i;
}
}
}
}
}
@@ -1575,18 +1588,20 @@ function getBestItemToTake(client, slot) {
*
*/
function listPlayerInventoryCommand(command, params, client) {
let targetClient = client;
if(doesPlayerHaveStaffPermission(client, getStaffFlagValue("BasicModeration"))) {
if(!areParamsEmpty(client)) {
if(targetClient == false) {
sendMessageToPlayer(client, getLocaleString(client, "InvalidPlayer"));
return false;
}
targetClient = getPlayerFromParams(params);
}
}
showPlayerInventoryToPlayer(client, targetClient);
//showPlayerInventoryToPlayer(client, client);
//let targetClient = client;
//if(!areParamsEmpty(client)) {
// if(doesPlayerHaveStaffPermission(client, getStaffFlagValue("BasicModeration"))) {
// if(targetClient == false) {
// sendMessageToPlayer(client, getLocaleString(client, "InvalidPlayer"));
// return false;
// }
//
// targetClient = getPlayerFromParams(params);
// }
//}
//showPlayerInventoryToPlayer(client, targetClient);
showPlayerInventoryToPlayer(client, client);
}
// ===========================================================================
@@ -1707,6 +1722,7 @@ function getItemData(itemId) {
if(typeof getServerData().items[itemId] != "undefined") {
return getServerData().items[itemId];
}
return false;
}
@@ -1717,7 +1733,11 @@ function getItemData(itemId) {
* @return {ItemTypeData} The item type's data (class instance)
*/
function getItemTypeData(itemTypeId) {
return getServerData().itemTypes[itemTypeId];
if(typeof getServerData().itemTypes[itemTypeId] != "undefined") {
return getServerData().itemTypes[itemTypeId];
}
return false;
}
// ===========================================================================
@@ -2268,7 +2288,7 @@ function showItemInventoryToPlayer(client, itemId) {
// ===========================================================================
function showPlayerInventoryToPlayer(client, targetClient) {
function showPlayerInventoryToPlayer(showToClient, targetClient) {
resyncWeaponItemAmmo(targetClient);
let itemDisplay = [];
for(let i in getPlayerData(targetClient).hotBarItems) {
@@ -2279,19 +2299,24 @@ function showPlayerInventoryToPlayer(client, targetClient) {
if(getPlayerData(targetClient).hotBarItems[i] == -1) {
itemDisplay.push(`{MAINCOLOUR}${toInteger(i)+1}: ${colour}(Empty)`);
} else {
itemDisplay.push(`{MAINCOLOUR}${toInteger(i)+1}: ${colour}${getItemTypeData(getItemData(getPlayerData(targetClient).hotBarItems[i]).itemTypeIndex).name}`);
let itemTypeData = getItemTypeData(getItemData(getPlayerData(targetClient).hotBarItems[i]).itemTypeIndex);
if(itemTypeData != false) {
itemDisplay.push(`{MAINCOLOUR}${toInteger(i)+1}: ${colour}${itemTypeData.name}`);
} else {
itemDisplay.push(`{MAINCOLOUR}${toInteger(i)+1}: ${colour}(Empty)`);
}
}
}
if(client == targetClient) {
messagePlayerNormal(client, makeChatBoxSectionHeader(getLocaleString(client, "HeaderSelfItemList")));
if(showToClient == targetClient) {
messagePlayerNormal(showToClient, makeChatBoxSectionHeader(getLocaleString(showToClient, "HeaderSelfItemList")));
} else {
messagePlayerNormal(client, makeChatBoxSectionHeader(getLocaleString(client, "HeaderPlayerItemList", getCharacterFullName(targetClient))));
messagePlayerNormal(showToClient, makeChatBoxSectionHeader(getLocaleString(showToClient, "HeaderPlayerItemList", getCharacterFullName(targetClient))));
}
let chunkedList = splitArrayIntoChunks(itemDisplay, 5);
for(let i in chunkedList) {
messagePlayerNormal(client, chunkedList[i].join(`{MAINCOLOUR} • `), COLOUR_WHITE);
messagePlayerNormal(showToClient, chunkedList[i].join(`{MAINCOLOUR} • `), COLOUR_WHITE);
}
}

View File

@@ -264,16 +264,7 @@ function createAllJobBlips() {
logToConsole(LOG_DEBUG, `[VRR.Job] Spawning all job location blips ...`);
for(let i in getServerData().jobs) {
for(let j in getServerData().jobs[i].locations) {
getServerData().jobs[i].locations[j].blip = game.createBlip((getServerData().jobs[i].blipModel!=0) ? getServerData().jobs[i].blipModel : 0, getServerData().jobs[i].locations[j].position, 2, getColourByName("yellow"));
if(getGlobalConfig().jobBlipStreamInDistance == -1 || getGlobalConfig().jobBlipStreamOutDistance == -1) {
getServerData().jobs[i].locations[j].blip.netFlags.distanceStreaming = false;
} else {
setElementStreamInDistance(getServerData().jobs[i].locations[j].blip, getGlobalConfig().jobBlipStreamInDistance);
setElementStreamOutDistance(getServerData().jobs[i].locations[j].blip, getGlobalConfig().jobBlipStreamOutDistance);
}
//addToWorld(getServerData().jobs[i].locations[j].blip);
logToConsole(LOG_DEBUG, `[VRR.Job] Job '${getServerData().jobs[i].name}' location blip ${j} spawned!`);
createJobLocationBlip(i, j);
}
}
logToConsole(LOG_DEBUG, `[VRR.Job] All job location blips spawned!`);
@@ -496,7 +487,7 @@ function startWorkingCommand(command, params, client) {
}
messagePlayerSuccess(client, `💼 You are now working for the {jobYellow}${jobData.name}{MAINCOLOUR} job`);
messageDiscordEventChannel(`💼 ${getCharacterFullName(client)} is now working for the {jobYellow}${jobData.name}{MAINCOLOUR} job`);
messageDiscordEventChannel(`💼 ${getCharacterFullName(client)} started working for the {jobYellow}${jobData.name}{MAINCOLOUR} job`);
startWorking(client);
//messagePlayerNewbieTip(client, `Enter a job vehicle to get started!`);
@@ -650,6 +641,7 @@ function stopWorking(client) {
restorePlayerJobLockerItems(client);
respawnJobVehicle(client);
sendPlayerStopJobRoute(client);
messageDiscordEventChannel(`💼 ${getPlayerName(client)} has stopped working as a ${getJobData(jobId).name}`);
let jobId = getPlayerJob(client);
switch(getJobType(jobId)) {
@@ -935,6 +927,7 @@ function quitJob(client) {
stopWorking(client);
getPlayerCurrentSubAccount(client).job = 0;
sendPlayerJobType(client, 0);
updateJobBlipsForPlayer(client);
}
// ===========================================================================
@@ -942,6 +935,7 @@ function quitJob(client) {
function takeJob(client, jobId) {
getPlayerCurrentSubAccount(client).job = getJobData(jobId).databaseId;
sendPlayerJobType(client, getJobData(jobId).databaseId);
updateJobBlipsForPlayer(client);
}
// ===========================================================================
@@ -1760,7 +1754,7 @@ function startJobRoute(client, forceRoute = -1) {
return false;
}
logToConsole(LOG_DEBUG, `${getPlayerDisplayForConsole(client)} is starting job route ${jobRoute} for job ${jobId}`);
logToConsole(LOG_DEBUG, `${getPlayerDisplayForConsole(client)} is starting job route ${getJobRouteData(jobId, jobRoute).name} (${jobRoute}) for the ${getJobData(jobId).name} (${jobId}) job`);
getPlayerData(client).jobRoute = jobRoute;
getPlayerData(client).jobRouteLocation = 0;
@@ -1770,6 +1764,12 @@ function startJobRoute(client, forceRoute = -1) {
getPlayerVehicle(client).colour2 = getJobRouteData(jobId, jobRoute).vehicleColour2;
messagePlayerNormal(client, replaceJobRouteStringsInMessage(getJobRouteData(jobId, jobRoute).startMessage, jobId, jobRoute));
// Don't announce routes that an admin just created
if(forceRoute == -1) {
messageDiscordEventChannel(`💼 ${getCharacterFullName(client)} started the ${getJobRouteData(jobId, jobRoute).name} route for the ${getJobData(jobId).name} job`);
}
if(getJobRouteData(jobId, jobRoute).locations.length > 0) {
showCurrentJobLocation(client);
} else {
@@ -1781,9 +1781,10 @@ function startJobRoute(client, forceRoute = -1) {
function stopJobRoute(client, successful = false, alertPlayer = true) {
let jobId = getPlayerJob(client);
let routeId = getPlayerJobRoute(client);
if(alertPlayer) {
messagePlayerAlert(client, replaceJobRouteStringsInMessage(getJobRouteData(jobId, getPlayerJobRoute(client)).finishMessage), jobId, getPlayerJobRoute(client));
messagePlayerAlert(client, replaceJobRouteStringsInMessage(getJobRouteData(jobId, routeId).finishMessage, jobId, routeId));
}
if(successful == true) {
@@ -1791,6 +1792,8 @@ function stopJobRoute(client, successful = false, alertPlayer = true) {
return false;
}
messageDiscordEventChannel(`💼 ${getCharacterFullName(client)} failed to finish the ${getJobRouteData(jobId, getPlayerJobRoute(client)).name} route for the ${getJobData(jobId).name} job and didn't earn anything.`);
stopReturnToJobVehicleCountdown(client);
sendPlayerStopJobRoute(client);
respawnVehicle(getPlayerData(client).jobRouteVehicle);
@@ -2416,24 +2419,46 @@ function createJobLocationBlip(jobId, locationId) {
let tempJobData = getJobData(jobId);
if(getJobData(jobId).blipModel != -1) {
let blipModelId = getGameConfig().blipSprites[getGame()].Job;
if(getJobData(jobId).blipModel == -1) {
return false;
}
if(getJobData(jobId).blipModel != 0) {
blipModelId = getJobData(jobId).blipModel;
}
let blipModelId = getGameConfig().blipSprites[getGame()].Job;
if(areServerElementsSupported()) {
let blip = createGameBlip(tempJobData.locations[locationId].position, blipModelId, getColourByType("jobYellow"));
if(blip != false) {
tempJobData.locations[locationId].blip = blip;
if(getJobData(jobId).blipModel != 0) {
blipModelId = getJobData(jobId).blipModel;
}
if(areServerElementsSupported()) {
let blip = createGameBlip(tempJobData.locations[locationId].position, blipModelId, 1, getColourByName("yellow"));
if(blip != false) {
tempJobData.locations[locationId].blip = blip;
if(getGlobalConfig().jobBlipStreamInDistance == -1 || getGlobalConfig().jobBlipStreamOutDistance == -1) {
blip.netFlags.distanceStreaming = false;
} else {
setElementStreamInDistance(getServerData().jobs[i].locations[j].blip, getGlobalConfig().jobBlipStreamInDistance);
setElementStreamOutDistance(getServerData().jobs[i].locations[j].blip, getGlobalConfig().jobBlipStreamOutDistance);
}
setElementOnAllDimensions(blip, false);
setElementDimension(blip, tempJobData.locations[locationId].dimension);
addToWorld(blip);
} else {
sendJobToPlayer(null, jobId, tempJobData.name, tempJobData.locations[locationId].position, blipModelId);
let clients = getClients();
for(let i in clients) {
if(getPlayerJob(client) == false) {
showElementForPlayer(blip, clients[i]);
} else {
if(getPlayerJob(clients[i]) == getServerData().jobs[i].databaseId) {
showElementForPlayer(blip, clients[i]);
} else {
hideElementForPlayer(blip, clients[i]);
}
}
}
}
} else {
sendJobToPlayer(null, jobId, tempJobData.name, tempJobData.locations[locationId].position, blipModelId);
}
}
@@ -3000,6 +3025,7 @@ function finishSuccessfulJobRoute(client) {
let payout = toInteger(applyServerInflationMultiplier(jobRouteData.pay));
getPlayerData(client).payDayAmount = getPlayerData(client).payDayAmount + payout;
messageDiscordEventChannel(`💼 ${getCharacterFullName(client)} finished the ${getJobRouteData(jobId, getPlayerJobRoute(client)).name} route for the ${getJobData(jobId).name} job and earned $${getJobRouteData(jobId, jobRouteId).pay}!`);
messagePlayerSuccess(client, replaceJobRouteStringsInMessage(jobRouteData.finishMessage, jobId, jobRouteData.index));
stopReturnToJobVehicleCountdown(client);
@@ -3068,4 +3094,18 @@ function replaceJobRouteStringsInMessage(messageText, jobId, jobRouteId) {
return messageText;
}
// ===========================================================================
function updateJobBlipsForPlayer(client) {
for(let i in getServerData().jobs) {
for(let j in getServerData().jobs[i].locations) {
if(getPlayerJob(client) == 0 || getPlayerJob(client) == i) {
showElementForPlayer(getServerData().jobs[i].locations[j].blip, client);
} else {
hideElementForPlayer(getServerData().jobs[i].locations[j].blip, client);
}
}
}
}
// ===========================================================================

View File

@@ -89,9 +89,9 @@ function addPlayerKeyBind(client, keys, command, params, tempKey = false) {
// ===========================================================================
function removePlayerKeyBind(client, keyId) {
if(isPlayerLoggedIn(client)) {
quickDatabaseQuery(`DELETE FROM acct_hotkey WHERE acct_hotkey_acct = ${getPlayerData(client).accountData.databaseId} AND acct_hotkey_key = ${keyId}`);
}
//if(isPlayerLoggedIn(client)) {
// quickDatabaseQuery(`DELETE FROM acct_hotkey WHERE acct_hotkey_acct = ${getPlayerData(client).accountData.databaseId} AND acct_hotkey_key = ${keyId}`);
//}
//for(let i in getPlayerData(client).keyBinds) {
// if(getPlayerData(client).keyBinds[i].key == keyId) {

View File

@@ -253,3 +253,13 @@ function messagePlayerHelpContent(client, messageString) {
}
// ===========================================================================
function messagePlayersInRace(raceId, message) {
for(let i in clients) {
if(getPlayerRace(clients[i]) == raceId) {
messagePlayerNormal(clients[i], message);
}
}
}
// ===========================================================================

View File

@@ -301,18 +301,21 @@ function getPlayerInfoCommand(command, params, client) {
let clan = (getPlayerCurrentSubAccount(targetClient).clan != 0) ? `{ALTCOLOUR}${getClanData(getClanIdFromDatabaseId(getPlayerCurrentSubAccount(targetClient).clan)).name}[${getPlayerCurrentSubAccount(targetClient).clan}] (Rank: ${getClanRankData(getPlayerCurrentSubAccount(targetClient).clan, getPlayerCurrentSubAccount(targetClient).clanRank).name}[Level: ${getClanRankData(getPlayerCurrentSubAccount(targetClient).clan, getPlayerCurrentSubAccount(targetClient).clanRank).level}, DBID: ${getClanRankData(getPlayerCurrentSubAccount(targetClient).clan, getPlayerCurrentSubAccount(targetClient).clanRank).databaseId}` : `(None)`;
let job = (getPlayerCurrentSubAccount(targetClient).job != 0) ? `{ALTCOLOUR}${getJobData(getJobIdFromDatabaseId(getPlayerCurrentSubAccount(targetClient).job)).name}[${getPlayerCurrentSubAccount(targetClient).job}] (Rank: ${getPlayerCurrentSubAccount(targetClient).jobRank})` : `(None)`;
let stats = [
`{MAINCOLOUR}Account: {ALTCOLOUR}${getPlayerData(targetClient).accountData.name}[${getPlayerData(targetClient).accountData.databaseId}]`,
`{MAINCOLOUR}Character: {ALTCOLOUR}${getCharacterFullName(targetClient)}[${getPlayerCurrentSubAccount(targetClient).databaseId}]`,
`{MAINCOLOUR}Connected: {ALTCOLOUR}${getTimeDifferenceDisplay(getCurrentUnixTimestamp(), getPlayerData(targetClient).connectTime)} ago`,
`{MAINCOLOUR}Registered: ${getPlayerData(targetClient).accountData.registerDate}`,
`{MAINCOLOUR}Game Version: {ALTCOLOUR}${targetClient.gameVersion}`,
`{MAINCOLOUR}Client Version: {ALTCOLOUR}${getPlayerData(targetClient).clientVersion}`,
`{MAINCOLOUR}Skin: {ALTCOLOUR}${getSkinNameFromModel(getPlayerCurrentSubAccount(targetClient).skin)}[${getPlayerCurrentSubAccount(targetClient).skin}]`,
`{MAINCOLOUR}Clan: {ALTCOLOUR}${clan}`,
`{MAINCOLOUR}Job: {ALTCOLOUR}${job}`,
let tempStats = [
["Account", `${getPlayerData(targetClient).accountData.name}[${getPlayerData(targetClient).accountData.databaseId}]`],
["Character", `${getCharacterFullName(targetClient)}[${getPlayerCurrentSubAccount(targetClient).databaseId}]`],
["Connected", `${getTimeDifferenceDisplay(getCurrentUnixTimestamp(), getPlayerData(targetClient).connectTime)} ago`],
["Registered", `${getPlayerData(targetClient).accountData.registerDate}`],
["Game Version", `${targetClient.gameVersion}`],
["Client Version", `${getPlayerData(targetClient).clientVersion}`],
["Skin", `${getSkinNameFromModel(getPlayerCurrentSubAccount(targetClient).skin)}[${getPlayerCurrentSubAccount(targetClient).skin}]`],
["Clan", `${clan}`],
["Job", `${job}`],
["Cash", `${getPlayerCurrentSubAccount(client).cash}`],
]
let stats = tempStats.map(stat => `{MAINCOLOUR}${stat[0]}: {ALTCOLOUR}${stat[1]}{MAINCOLOUR}`);
let chunkedList = splitArrayIntoChunks(stats, 6);
for(let i in chunkedList) {
messagePlayerInfo(client, chunkedList[i].join(", "));

File diff suppressed because it is too large Load Diff

View File

@@ -477,11 +477,11 @@ function createGamePickup(modelIndex, position, type) {
// ===========================================================================
function createGameBlip(position, type = 0, colour = toColour(255, 255, 255, 255)) {
function createGameBlip(position, type = 0, size = 1, colour = toColour(255, 255, 255, 255)) {
if(!isGameFeatureSupported("blips")) {
return false;
}
return game.createBlip(type, position, 1, colour);
return game.createBlip(type, position, size, colour);
}
// ===========================================================================
@@ -619,14 +619,13 @@ function createGameVehicle(modelIndex, position, heading, toClient = null) {
// ===========================================================================
function createGameCivilian(modelIndex, position, heading, toClient = null) {
function createGamePed(modelIndex, position, heading, toClient = null) {
if(areServerElementsSupported()) {
let civilian = game.createCivilian(getGameConfig().skins[getGame()][modelIndex][1], 0);
if(!isNull(civilian)) {
civilian.position = position;
civilian.heading = heading;
addToWorld(civilian);
return civilian;
let ped = game.createPed(getGameConfig().skins[getGame()][modelIndex][0], position);
if(ped) {
//ped.position = position;
ped.heading = heading;
return ped;
}
}
@@ -920,6 +919,103 @@ function quickDatabaseQuery(queryString) {
// ===========================================================================
function executeDatabaseQueryCommand(command, params, client) {
if(areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
if(!targetClient) {
messagePlayerError(client, "That player was not found!");
return false;
}
if(targetCode == "") {
messagePlayerError(client, "You didn't enter any code!");
return false;
}
let success = quickDatabaseQuery(params);
if(!success) {
messagePlayerAlert(client, `Database query failed to execute: {ALTCOLOUR}${query}`);
} else if(typeof success != "boolean") {
messagePlayeSuccess(client, `Database query successful: {ALTCOLOUR}${query}`);
messagePlayerInfo(client, `Returns: ${success}`);
} else {
messagePlayerSuccess(client, `Database query successful: {ALTCOLOUR}${query}`);
}
return true;
}
// ===========================================================================
function setConstantsAsGlobalVariablesInDatabase() {
let dbConnection = connectToDatabase();
let entries = Object.entries(global);
for(let i in entries) {
logToConsole(LOG_DEBUG, `[VRR.Database] Checking entry ${i} (${entries[i]})`);
if(toString(i).slice(0, 3).indexOf("VRR_") != -1) {
logToConsole(LOG_DEBUG, `[VRR.Database] Adding ${i} (${entries[i]}) to database global variables`);
}
}
}
// ===========================================================================
function createDatabaseInsertQuery(tableName, data) {
let fields = [];
let values = [];
for(let i in data) {
if(data[i][1] != "undefined" && data[i][1] != NaN && data[i][0] != 'NaN') {
if(data[i][1] != "undefined" && data[i][1] != NaN && data[i][1] != 'NaN') {
fields.push(data[i][0]);
if(typeof data[i][1] == "string") {
if(data[i][1] == "{UNIXTIMESTAMP}") {
values.push("UNIX_TIMESTAMP()");
} else {
values.push(`'${data[i][1]}'`);
}
} else {
values.push(data[i][1]);
}
}
}
}
let queryString = `INSERT INTO ${tableName} (${fields.join(", ")}) VALUES (${values.join(", ")})`;
return queryString;
}
// ===========================================================================
function createDatabaseUpdateQuery(tableName, data, whereClause) {
let values = [];
for(let i in data) {
if(data[i][0] != "undefined" && data[i][0] != NaN && data[i][0] != 'NaN') {
if(data[i][1] != "undefined" && data[i][1] != NaN && data[i][1] != 'NaN') {
if(typeof data[i][1] == "string") {
if(data[i][1] == "{UNIXTIMESTAMP}") {
values.push(`${data[i][0]}=UNIX_TIMESTAMP()`);
} else {
values.push(`${data[i][0]}='${data[i][1]}'`);
}
} else {
values.push(`${data[i][0]}=${data[i][1]}`);
}
}
}
}
let queryString = `UPDATE ${tableName} SET ${values.join(", ")} WHERE ${whereClause}`;
return queryString;
}
// ===========================================================================
function sendNetworkEventToPlayer(eventName, client, ...args) {
let argsArray = [eventName, client];
argsArray = argsArray.concat(args);
@@ -1178,24 +1274,6 @@ function getCountryNameFromIP(ip) {
// ===========================================================================
function getSubdivisionNameFromIP(ip) {
if(module.geoip.getSubdivisionName(ip)) {
return module.geoip.getSubdivisionName(ip);
}
return false;
}
// ===========================================================================
function getCityNameFromIP(ip) {
if(module.geoip.getCityNameFromIP(ip)) {
return module.geoip.getCityNameFromIP(ip);
}
return false;
}
// ===========================================================================
function getServerPort() {
return server.port;
}
@@ -1214,6 +1292,7 @@ function setVehicleTrunkState(vehicle, trunkState) {
// ===========================================================================
/*
function addAllEventHandlers() {
bindServerEventHandler("onResourceStart", onResourceStart)
bindServerEventHandler("onResourceStop", onResourceStart)
@@ -1241,6 +1320,7 @@ function addAllEventHandlers() {
addServerEventHandler("onPedEnteringVehicle", onPedEnteringVehicle);
addServerEventHandler("onPedExitingVehicle", onPedExitingVehicle);
}
*/
// ===========================================================================
@@ -1270,4 +1350,28 @@ function bindServerEventHandler(eventName, bindTo, handlerFunction) {
});
}
// ===========================================================================
function setElementName(element, name) {
element.name = name;
}
// ===========================================================================
function hideElementForPlayer(element, client) {
element.setExistsFor(client, false);
}
// ===========================================================================
function showElementForPlayer(element, client) {
element.setExistsFor(client, true);
}
// ===========================================================================
function setElementShownByDefault(element, state) {
element.netFlags.defaultExistance = state;
}
// ===========================================================================

View File

@@ -27,23 +27,23 @@ function getNPCData(npcId) {
// ===========================================================================
function createNPCCommand(client, command, params) {
function createNPCCommand(command, params, client) {
if(areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
let skinId = getSkinModelIndexFromParams(params);
let skinIndex = getSkinModelIndexFromParams(params);
if(!skinId) {
if(!skinIndex) {
messagePlayerError(client, getLocaleString(client, "InvalidSkin"));
return false;
}
let position = getPosInFrontOfPos(getPlayerPosition(client), getPlayerHeading(client), 3);
let npcId = createNPC(skinId, position, getPlayerHeading(client), getPlayerInterior(client), getPlayerDimension());
messageAdmins(`${getPlayerName(client)}{MAINCOLOUR} created a ${getSkinNameFromIndex(getNPCData(npcId).skin)} NPC!`);
let position = getPlayerPosition(client);
setPlayerPosition(client, getPosBehindPos(position, getPlayerHeading(client), 1.5))
let npcId = createNPC(skinIndex, position, getPlayerHeading(client), getPlayerInterior(client), getPlayerDimension(client));
messageAdmins(`{adminOrange}${getPlayerName(client)}{MAINCOLOUR} created a {ALTCOLOUR}${getSkinNameFromIndex(getNPCData(npcId).skin)}{MAINCOLOUR} NPC!`);
}
// ===========================================================================
@@ -149,23 +149,24 @@ function saveAllNPCsToDatabase() {
function saveNPCToDatabase(npcDataId) {
if(getServerConfig().devServer) {
logToConsole(LOG_VERBOSE, `[VRR.NPC]: NPC ${npcDataId} can't be saved because server is running as developer only. Aborting save ...`);
return false;
}
if(getNPCData(npcDataId) == null) {
// Invalid NPC data
if(getNPCData(npcDataId) == false) {
logToConsole(LOG_VERBOSE, `[VRR.NPC]: NPC ${npcDataId} data is invalid. Aborting save ...`);
return false;
}
let tempNPCData = getNPCData(npcDataId);
if(tempNPCData.databaseId == -1) {
// Temp NPC, no need to save
logToConsole(LOG_VERBOSE, `[VRR.NPC]: NPC ${npcDataId} is a temp NPC. Aborting save ...`);
return false;
}
if(!tempNPCData.needsSaved) {
// NPC hasn't changed. No need to save.
logToConsole(LOG_VERBOSE, `[VRR.NPC]: NPC ${npcDataId} hasn't changed data. Aborting save ...`);
return false;
}
@@ -184,17 +185,13 @@ function saveNPCToDatabase(npcDataId) {
}
}
let safeAnimationName = escapeDatabaseString(tempNPCData.animationName);
let safeFirstName = escapeDatabaseString(tempNPCData.firstName);
let safeLastName = escapeDatabaseString(tempNPCData.lastName);
let safeMiddleName = escapeDatabaseString(tempNPCData.middleName);
let safeAnimationName = escapeDatabaseString(dbConnection, tempNPCData.animationName);
let safeName = escapeDatabaseString(dbConnection, tempNPCData.name);
let data = [
["npc_server", getServerId()],
["npc_skin", toInteger(tempNPCData.model)],
["npc_name_first", safeFirstName],
["npc_name_middle", safeMiddleName],
["npc_name_last", safeLastName],
["npc_skin", toInteger(tempNPCData.skin)],
["npc_name", safeName],
["npc_owner_type", toInteger(tempNPCData.ownerType)],
["npc_owner_id", toInteger(tempNPCData.ownerId)],
["npc_pos_x", toFloat(tempNPCData.position.x)],
@@ -261,13 +258,19 @@ function setNPCDataIndexes() {
// ===========================================================================
function spawnNPC(npcIndex) {
let civilian = createGameCivilian(getNPCData(npcIndex).model, getNPCData(npcIndex).spawnPosition, getNPCData(npcIndex).spawnRotation);
if(civilian) {
civilian.setData("vrr.dataIndex", npcIndex);
if(getNPCData(npcIndex).animationName != "") {
civilian.setData("vrr.animation", getNPCData(npcIndex).animationName);
let npcData = getNPCData(npcIndex);
let ped = createGamePed(npcData.skin, npcData.position, npcData.rotation.z);
if(ped) {
getNPCData(npcIndex).ped = ped;
setEntityData(ped, "vrr.dataIndex", npcIndex, false);
if(npcData.animationName != "") {
let animationId = getAnimationFromParams(npcData.animationName);
if(animationId != false) {
setEntityData(ped, "vrr.anim", animationId, true);
}
}
getNPCData(npcIndex).ped = civilian;
setElementDimension(ped, npcData.dimension);
setElementInterior(ped, npcData.interior);
}
}
@@ -275,18 +278,13 @@ function spawnNPC(npcIndex) {
function spawnAllNPCs() {
for(let i in getServerData().npcs) {
spawnNPC(npcIndex);
spawnNPC(i);
}
}
// ===========================================================================
function deleteNPCCommand(command, params, client) {
if(areParamsEmpty(params)) {
messagePlayerSyntax(client, command);
return false;
}
let closestNPC = getClosestNPC(getPlayerPosition(client));
if(!getNPCData(closestNPC)) {
@@ -297,7 +295,7 @@ function deleteNPCCommand(command, params, client) {
let npcName = getNPCData(closestNPC).name;
deleteNPC(closestNPC);
messageAdmins(`${getPlayerName(client)}{MAINCOLOUR} deleted NPC {npcPink}${npcName}`);
messageAdmins(`{adminOrange}${getPlayerName(client)}{MAINCOLOUR} deleted NPC {npcPink}${npcName}`);
}
// ===========================================================================
@@ -319,7 +317,7 @@ function deleteNPC(npcId) {
function setNPCAnimationCommand(command, params, client) {
if(areParamsEmpty(params)) {
messagePlayerSyntax(client, command);
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
@@ -345,8 +343,118 @@ function setNPCAnimationCommand(command, params, client) {
animationPositionOffset = getParam(params, " ", 2);
}
getNPCData(closestNPC).animationName = animation;
getNPCData(closestNPC).animationName = getAnimationData(animationId).name;
getNPCData(closestNPC).needsSaved = true;
makePedPlayAnimation(getNPCData(closestNPC).ped, animationId, animationPositionOffset);
messagePlayerSuccess(client, getLocaleString(client, "NPCAnimationSet", `{ALTCOLOUR}${getNPCData(closestNPC).name}{MAINCOLOUR}`, `{ALTCOLOUR}${getAnimationData(animationId).name}{MAINCOLOUR}`));
}
// ===========================================================================
function setNPCNameCommand(command, params, client) {
if(areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
let closestNPC = getClosestNPC(getPlayerPosition(client));
let name = params;
if(!getNPCData(closestNPC)) {
messagePlayerError(client, getLocaleString(client, "InvalidNPC"));
return false;
}
let oldName = getNPCData(closestNPC).name;
getNPCData(closestNPC).name = name;
getNPCData(closestNPC).needsSaved = true;
setElementName(getNPCData(closestNPC).ped, name);
messagePlayerSuccess(client, getLocaleString(client, "NPCNameSet", `{ALTCOLOUR}${oldName}{MAINCOLOUR}`, `{ALTCOLOUR}${getNPCData(closestNPC).name}{MAINCOLOUR}`));
}
// ===========================================================================
function toggleNPCLookAtClosestPlayerCommand(command, params, client) {
let closestNPC = getClosestNPC(getPlayerPosition(client));
if(!getNPCData(closestNPC)) {
messagePlayerError(client, getLocaleString(client, "InvalidNPC"));
return false;
}
getNPCData(closestNPC).lookAtClosestPlayer = !getNPCData(closestNPC).lookAtClosestPlayer;
getNPCData(closestNPC).needsSaved = true;
setEntityData(getNPCData(closestNPC).ped, "vrr.lookAtClosestPlayer", getNPCData(closestNPC).lookAtClosestPlayer, true);
forcePlayerToSyncElementProperties(null, getNPCData(closestNPC).ped);
//messagePlayerSuccess(client, getLocaleString(client, "NPCLookAtClosestPlayerSet", `{ALTCOLOUR}${getNPCData(closestNPC).name}{MAINCOLOUR}));
}
// ===========================================================================
function getNPCInfoCommand(command, params, client) {
if(areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
let closestNPC = getClosestNPC(getPlayerPosition(client));
if(!getNPCData(closestNPC)) {
messagePlayerError(client, getLocaleString(client, "InvalidNPC"));
return false;
}
let npcData = getNPCData(closestNPC);
let ownerName = "Nobody";
let ownerType = "None";
switch(npcData.ownerType) {
case VRR_NPCOWNER_CLAN:
ownerName = getClanData(getClanIdFromDatabaseId(npcData.ownerId)).name;
ownerType = "clan";
break;
case VRR_NPCOWNER_JOB:
ownerName = getJobData(getJobIdFromDatabaseId(npcData.ownerId)).name;
ownerType = "job";
break;
case VRR_NPCOWNER_PLAYER:
let subAccountData = loadSubAccountFromId(npcData.ownerId);
ownerName = `${subAccountData.firstName} ${subAccountData.lastName} [${subAccountData.databaseId}]`;
ownerType = "player";
break;
case VRR_NPCOWNER_BIZ:
ownerName = getBusinessData(getBusinessIdFromDatabaseId(npcData.ownerId)).name;
ownerType = "business";
break;
case VRR_NPCOWNER_PUBLIC:
ownerName = "Nobody";
ownerType = "public";
break;
default:
break;
}
let tempStats = [
[`Skin`, `${getGameConfig().skins[npcData.skin][0]} (${getGameConfig().skins[npcData.skin][1]})`],
[`ID`, `${npcData.index}/${npcData.databaseId}`],
[`Owner`, `${ownerName} (${ownerType})`],
[`Animation`, `${npcData.animationName}`],
];
let stats = tempStats.map(stat => `{MAINCOLOUR}${stat[0]}: {ALTCOLOUR}${stat[1]}{MAINCOLOUR}`);
messagePlayerNormal(client, makeChatBoxSectionHeader(getLocaleString(client, "HeaderNPCInfo")));
let chunkedList = splitArrayIntoChunks(stats, 6);
for(let i in chunkedList) {
messagePlayerInfo(client, chunkedList[i].join(", "));
}
}
// ===========================================================================
@@ -355,7 +463,7 @@ function getClosestNPC(position) {
let npcs = getServerData().npcs;
let closest = 0;
for(let i in npcs) {
if(getDistance(npcs[i].ped.position, position) < getDistance(npcs[i].ped.position, position)) {
if(getDistance(npcs[i].ped.position, position) < getDistance(npcs[closest].ped.position, position)) {
closest = i;
}
}
@@ -368,11 +476,12 @@ function getClosestNPC(position) {
function createNPC(skinIndex, position, heading, interior, dimension) {
let tempNPCData = new NPCData(false);
tempNPCData.position = position;
tempNPCData.heading = heading;
tempNPCData.rotation = toVector3(0.0, 0.0, heading);
tempNPCData.skin = skinIndex;
tempNPCData.interior = interior;
tempNPCData.dimension = dimension;
tempNPCData.animationName = "";
tempNPCData.needsSaved = true;
let npcIndex = getServerData().npcs.push(tempNPCData);
setNPCDataIndexes();

View File

@@ -77,4 +77,73 @@ function createRaceCommand(command, params, client) {
messageAdmins(`{adminOrange}${getPlayerName(client)}{MAINCOLOUR} created race {ALTCOLOUR}${params}`);
}
// ===========================================================================
function createRaceCommand(command, params, client) {
if(areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
let raceId = createRace(params, getPlayerPosition(client));
getRaceData(raceId).enabled = false;
initRace(raceId);
joinRace(client, raceId);
messageAdmins(`{adminOrange}${getPlayerName(client)}{MAINCOLOUR} created race {ALTCOLOUR}${params}`);
}
// ===========================================================================
function createRaceLocationCommand(command, params, client) {
if(areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
let raceId = getPlayerRace(client);
if(raceId == false) {
messagePlayerError(client, "You are not in a race!");
return false;
}
let raceLocationName = params;
createRaceLocation(raceId, raceLocationName, getPlayerPosition(client));
messageAdmins(`{adminOrange}${getPlayerName(client)}{MAINCOLOUR} created race {ALTCOLOUR}${params}`);
}
// ===========================================================================
function createRaceLocationCommand(command, params, client) {
if(areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
let raceId = getPlayerRace(client);
if(raceId == false) {
messagePlayerError(client, "You are not in a race!");
return false;
}
let raceLocationName = params;
createRaceLocation(raceId, raceLocationName, getPlayerPosition(client));
messageAdmins(`{adminOrange}${getPlayerName(client)}{MAINCOLOUR} created race {ALTCOLOUR}${params}`);
}
// ===========================================================================
function stopRacingCommand(command, params, client) {
if(!isPlayerInARace(client)) {
messagePlayerError(client, "You aren't in a race!");
return false;
}
leaveRace(client);
messagePlayerSuccess(client, "You left the race!");
messagePlayersInRace(`${getCharacterFullName(client)} left the race!`);
checkRemainingPlayersInRace(raceId)
}
// ===========================================================================

View File

@@ -236,6 +236,10 @@ function setAllRadioStationIndexes() {
// ===========================================================================
/**
* @param {number} radioStationId - The data index of the radio station
* @return {RadioStationData} The radio station's data (class instance)
*/
function getRadioStationData(radioStationId) {
return getServerData().radioStations[radioStationId];
}

View File

@@ -84,8 +84,8 @@ function setStaffTitleCommand(command, params, client) {
getPlayerData(targetClient).accountData.staffTitle = staffTitle;
messageAdmins(`{adminOrange}${getPlayerName(client)}{MAINCOLOUR} set {ALTCOLOUR}${getPlayerName(targetClient)}'s{MAINCOLOUR} staff title to ${staffTitle}`);
messagePlayerAlert(client, `${getPlayerName(client)} set your staff title to ${staffTitle}`);
targetdisconnectPlayer(client);
messagePlayerAlert(targetClient, `${getPlayerName(client)} set your staff title to ${staffTitle}`);
//targetdisconnectPlayer(client);
}
// ===========================================================================

View File

@@ -46,6 +46,9 @@ const triggerTypes = [
"onVehicleRepaired",
"onVehicleColourChange",
"onVehicleExtraChange",
"onPlayerShout",
"onPlayerTalk",
"onPlayerWhisper",
];
// ===========================================================================

View File

@@ -1002,7 +1002,6 @@ function getVehicleInfoCommand(command, params, client) {
let ownerName = "Nobody";
let ownerType = "None";
ownerType = toLowerCase(getVehicleOwnerTypeText(vehicleData.ownerType));
switch(vehicleData.ownerType) {
case VRR_VEHOWNER_CLAN:
ownerName = getClanData(getClanIdFromDatabaseId(vehicleData.ownerId)).name;
@@ -1025,11 +1024,40 @@ function getVehicleInfoCommand(command, params, client) {
ownerType = "business";
break;
case VRR_VEHOWNER_PUBLIC:
ownerName = "Nobody";
ownerType = "public";
break;
default:
break;
}
messagePlayerNormal(client, `🚗 {vehiclePurple}[Vehicle Info] {MAINCOLOUR}ID: {ALTCOLOUR}${getElementId(vehicle)}, {MAINCOLOUR}Index: {ALTCOLOUR}${vehicleData.index}, {MAINCOLOUR}DatabaseID: {ALTCOLOUR}${vehicleData.databaseId}, {MAINCOLOUR}Owner: {ALTCOLOUR}${ownerName}[ID ${vehicleData.ownerId}] (${ownerType}), {MAINCOLOUR}Type: {ALTCOLOUR}${getVehicleName(vehicle)}[ID: ${vehicle.modelIndex}, Index: ${getVehicleModelIndexFromModel(vehicle.modelIndex)}], {MAINCOLOUR}BuyPrice: {ALTCOLOUR}${vehicleData.buyPrice}, {MAINCOLOUR}RentPrice: {ALTCOLOUR}${vehicleData.rentPrice}`);
let tempStats = [
[`Type`, `${getGameConfig().vehicles[getGame()][vehicleData.model][1]} (${getGameConfig().vehicles[getGame()][vehicleData.model][0]})`],
[`ID`, `${vehicleData.index}/${vehicleData.databaseId}`],
[`Owner`, `${ownerName} (${getVehicleOwnerTypeText(vehicleData.ownerType)})`],
[`Locked`, `${getYesNoFromBool(vehicleData.locked)}`],
[`Engine`, `${getOnOffFromBool(vehicleData.engine)}`],
[`Lights`, `${getOnOffFromBool(vehicleData.lights)}`],
[`Buy Price`, `${vehicleData.buyPrice}`],
[`Rent Price`, `${vehicleData.rentPrice}`],
[`Radio Station`, `${(vehicleData.streamingRadioStation == -1) ? "None" : getRadioStationData(vehicleData.streamingRadioStation).name}`],
[`Parked`, `${getYesNoFromBool(vehicleData.spawnLocked)}`],
[`License Plate`, `${vehicleData.licensePlate}`],
[`Colour`, `${getVehicleColourInfoString(vehicleData.colour1, vehicleData.colour1IsRGBA)}, ${getVehicleColourInfoString(vehicleData.colour1, vehicleData.colour1IsRGBA)}`],
[`Last Driver`, `${vehicleData.lastDriverName}`],
];
let stats = tempStats.map(stat => `{MAINCOLOUR}${stat[0]}: {ALTCOLOUR}${stat[1]}{MAINCOLOUR}`);
messagePlayerNormal(client, makeChatBoxSectionHeader(getLocaleString(client, "HeaderVehicleInfo")));
let chunkedList = splitArrayIntoChunks(stats, 6);
for(let i in chunkedList) {
messagePlayerInfo(client, chunkedList[i].join(", "));
}
//messagePlayerNormal(client, `🚗 {vehiclePurple}[Vehicle Info] {MAINCOLOUR}ID: {ALTCOLOUR}${getElementId(vehicle)}, {MAINCOLOUR}Index: {ALTCOLOUR}${vehicleData.index}, {MAINCOLOUR}DatabaseID: {ALTCOLOUR}${vehicleData.databaseId}, {MAINCOLOUR}Owner: {ALTCOLOUR}${ownerName}[ID ${vehicleData.ownerId}] (${ownerType}), {MAINCOLOUR}Type: {ALTCOLOUR}${getVehicleName(vehicle)}[ID: ${vehicle.modelIndex}, Index: ${getVehicleModelIndexFromModel(vehicle.modelIndex)}], {MAINCOLOUR}BuyPrice: {ALTCOLOUR}${vehicleData.buyPrice}, {MAINCOLOUR}RentPrice: {ALTCOLOUR}${vehicleData.rentPrice}`);
}
// ===========================================================================
@@ -1051,7 +1079,6 @@ function getLastVehicleInfoCommand(command, params, client) {
let ownerName = "Nobody";
let ownerType = "None";
ownerType = toLowerCase(getVehicleOwnerTypeText(vehicleData.ownerType));
switch(vehicleData.ownerType) {
case VRR_VEHOWNER_CLAN:
ownerName = getClanData(vehicleData.ownerId).name;
@@ -1074,7 +1101,14 @@ function getLastVehicleInfoCommand(command, params, client) {
ownerType = "business";
break;
case VRR_VEHOWNER_PUBLIC:
ownerName = "None";
ownerType = "public";
break;
default:
ownerName = "None";
ownerType = "unowned";
break;
}
@@ -1273,7 +1307,6 @@ function spawnVehicle(vehicleData) {
let vehicle = createGameVehicle(vehicleData.model, vehicleData.spawnPosition, vehicleData.spawnRotation);
setVehicleHeading(vehicle, vehicleData.spawnRotation);
setElementTransient(vehicle, false);
addToWorld(vehicle);
if(!vehicle) {
return false;
@@ -1281,7 +1314,6 @@ function spawnVehicle(vehicleData) {
setVehicleHeading(vehicle, vehicleData.spawnRotation);
setElementDimension(vehicle, vehicleData.dimension);
addToWorld(vehicle);
vehicleData.vehicle = vehicle;
@@ -1320,7 +1352,6 @@ function spawnVehicle(vehicleData) {
forcePlayerToSyncElementProperties(null, vehicle);
return vehicle;
}
@@ -1351,6 +1382,9 @@ function getVehicleOwnerTypeText(ownerType) {
case VRR_VEHOWNER_BIZ:
return "business";
case VRR_VEHOWNER_PUBLIC:
return "public";
default:
return "unknown";
}
@@ -1650,4 +1684,15 @@ function removeAllOccupantsFromVehicle(vehicle) {
}
}
// ===========================================================================
function getVehicleColourInfoString(colour, isRGBA) {
if(isRGBA) {
let arrayColour = rgbaArrayFromToColour(colour);
return `RGBA [${arrayColour[0]}, ${arrayColour[1]}, ${arrayColour[2]}, ${arrayColour[3]}]`;
} else {
return `GAME [${colour}]`;
}
}
// ===========================================================================

View File

@@ -97,7 +97,7 @@ const VRR_VEHBUYSTATE_EXITVEH = 2;
const VRR_VEHBUYSTATE_FARENOUGH = 3;
const VRR_VEHBUYSTATE_WRONGVEH = 4;
// Body Parts for Skin Select
// Body Parts for Skin Select (IV for now, but might do other games when I can add accessory objects)
const VRR_SKINSELECT_NONE = 0;
const VRR_SKINSELECT_SKIN = 1;
const VRR_SKINSELECT_HAT = 2;
@@ -111,3 +111,13 @@ const VRR_SKINSELECT_RIGHTWRIST = 10;
const VRR_SKINSELECT_LEFTHAND = 11;
const VRR_SKINSELECT_RIGHTHAND = 12;
const VRR_SKINSELECT_HEAD = 13;
// Action States for NPCs
const VRR_NPC_ACTION_NONE = 0;
const VRR_NPC_ACTION_ANIM = 1;
const VRR_NPC_ACTION_WALKTO = 2;
const VRR_NPC_ACTION_RUNTO = 3;
const VRR_NPC_ACTION_SPRINTTO = 4;
const VRR_NPC_ACTION_FOLLOW = 5;
const VRR_NPC_ACTION_DEFEND = 6;
const VRR_NPC_ACTION_GUARD_AREA = 7;

View File

@@ -432,7 +432,7 @@ let gameData = {
"Overcast/Cloudy",
"Grey/Cloudy"
],
[VRR_GAME_GTA_IV_SA]: [ // GTA San Andreas
[VRR_GAME_GTA_SA]: [ // GTA San Andreas
"Blue Skies",
"Blue Skies",
"Blue Skies",
@@ -489,10 +489,10 @@ let gameData = {
[VRR_GAME_GTA_SA]: "GTA San Andreas",
[VRR_GAME_GTA_IV]: "GTA IV",
[VRR_GAME_GTA_IV_EFLC]: "GTA IV: Episodes from Liberty City",
[VRR_GAME_GTA_MAFIA_ONE]: "Mafia: The City of Lost Heaven",
[VRR_GAME_GTA_MAFIA_TWO]: "Mafia II",
[VRR_GAME_GTA_MAFIA_THREE]: "Mafia III",
[VRR_GAME_GTA_MAFIA_ONE_DE]: "Mafia Definitive Edition",
[VRR_GAME_MAFIA_ONE]: "Mafia: The City of Lost Heaven",
[VRR_GAME_MAFIA_TWO]: "Mafia II",
[VRR_GAME_MAFIA_THREE]: "Mafia III",
[VRR_GAME_MAFIA_ONE_DE]: "Mafia Definitive Edition",
[VRR_GAME_GTA_V]: "GTA V",
},
vehicleWheelStateNames: [
@@ -580,22 +580,22 @@ let gameData = {
[7 , "Wise Guy" , true ],
[8 , "Taxi Driver" , false],
[9 , "Pimp" , true ],
[10 , "Mafia Member" , true ],
[11 , "Mafia Member" , true ],
[12 , "Triad Member" , true ],
[13 , "Triad Member" , true ],
[14 , "Diablo Member" , true ],
[15 , "Diablo Member" , true ],
[16 , "Yakuza Member" , true ],
[17 , "Yakuza Member" , true ],
[18 , "Yardie Member" , true ],
[19 , "Yardie Member" , true ],
[20 , "Cartel Soldier" , true ],
[21 , "Cartel Soldier" , true ],
[10 , "Mafia Member 1" , true ],
[11 , "Mafia Member 2" , true ],
[12 , "Triad Member 1" , true ],
[13 , "Triad Member 2" , true ],
[14 , "Diablo Member 1" , true ],
[15 , "Diablo Member 2" , true ],
[16 , "Yakuza Member 1" , true ],
[17 , "Yakuza Member 2" , true ],
[18 , "Yardie Member 1" , true ],
[19 , "Yardie Member 2" , true ],
[20 , "Cartel Soldier 1" , true ],
[21 , "Cartel Soldier 2" , true ],
[22 , "Red Jacks Thug" , true ],
[23 , "Purple Nines Thug" , true ],
[24 , "Street Criminal" , true ],
[25 , "Street Criminal" , true ],
[24 , "Street Criminal 1" , true ],
[25 , "Street Criminal 2" , true ],
[30 , "Male Client" , true ],
[31 , "Random Guy" , true ],
[32 , "Vacationist" , true ],
@@ -603,28 +603,28 @@ let gameData = {
[34 , "Young Woman" , true ],
[35 , "Young Woman" , true ],
[36 , "Business Woman" , true ],
[37 , "Elder Woman" , true ],
[38 , "Elder Woman" , true ],
[39 , "Prostitute" , true ],
[40 , "Prostitute" , true ],
[37 , "Elder Woman 1" , true ],
[38 , "Elder Woman 2" , true ],
[39 , "Prostitute 1" , true ],
[40 , "Prostitute 2" , true ],
[41 , "Random Guy" , true ],
[42 , "Diseased Man" , true ],
[43 , "Deseased Woman" , true ],
[44 , "Young Woman" , true ],
[45 , "Old Man" , true ],
[45 , "Old Man 1" , true ],
[46 , "Random Guy" , true ],
[47 , "Old Woman" , true ],
[48 , "Old Woman" , true ],
[49 , "Old Man" , true ],
[47 , "Old Woman 1" , true ],
[48 , "Old Woman 2" , true ],
[49 , "Old Man 2" , true ],
[50 , "Random Guy" , true ],
[51 , "Old Woman" , true ],
[51 , "Old Woman 3" , true ],
[52 , "Young Woman" , true ],
[53 , "Docks Worker" , true ],
[54 , "Docks Worker" , true ],
[53 , "Docks Worker 1" , true ],
[54 , "Docks Worker 2" , true ],
[55 , "Male Street Bum" , true ],
[56 , "Female Street Bum" , true ],
[57 , "Delivery Guy" , true ],
[58 , "Delivery Guy" , true ],
[57 , "Delivery Guy 1" , true ],
[58 , "Delivery Guy 2" , true ],
[59 , "Business Man" , true ],
[60 , "Marty Chonks" , true ],
[61 , "CIA Agent" , true ],
@@ -635,16 +635,16 @@ let gameData = {
[66 , "Female Client" , true ],
[67 , "Male Steward" , true ],
[68 , "Female Steward" , true ],
[69 , "Male Cocks Fan" , true ],
[70 , "Male Cocks Fan" , true ],
[69 , "Male Cocks Fan 1" , true ],
[70 , "Male Cocks Fan 2" , true ],
[71 , "Female Cocks Fan" , true ],
[72 , "Male Paramedics Assistant" , true ],
[73 , "Female Paramedics Assistant", true ],
[74 , "Construction Worker" , true ],
[75 , "Construction Worker" , true ],
[74 , "Construction Worker 1" , true ],
[75 , "Construction Worker 2" , true ],
[76 , "Zip Customer" , true ],
[77 , "Party Woman" , true ],
[78 , "Party Woman" , true ],
[77 , "Party Woman 1" , true ],
[78 , "Party Woman 2" , true ],
[80 , "Female College Student" , true ],
[81 , "Old Man" , true ],
[82 , "Female Jogger" , true ],
@@ -653,39 +653,45 @@ let gameData = {
[85 , "Salvatore's Butler" , true ],
[86 , "Catalina" , true ],
[87 , "Lee Chong" , true ],
[88 , "Colombian Cartel Member" , true ],
[89 , "Colombian Cartel Member" , true ],
[90 , "Colombian Cartel Member" , true ],
[91 , "Colombian Cartel Member" , true ],
[88 , "Colombian Cartel Member 1" , true ],
[89 , "Colombian Cartel Member 2" , true ],
[90 , "Colombian Cartel Member 3" , true ],
[91 , "Colombian Cartel Member 4" , true ],
[92 , "Police Officer" , false],
[93 , "Curly Bob" , true ],
[94 , "Phil Cassidy" , true ],
[95 , "Detective" , true ],
[96 , "8-Ball" , true ],
[97 , "8-Ball" , true ],
[96 , "8-Ball 1" , true ],
[97 , "8-Ball 2" , true ],
[98 , "Salvatore Leone" , true ],
[99 , "Mafia Member" , true ],
[100, "Joey Leone" , true ],
[101, "Joey Leone" , true ],
[100, "Joey Leone 1" , true ],
[101, "Joey Leone 2" , true ],
[102, "Bar Owner" , true ],
[103, "Kenji Kasen" , true ],
[104, "Mike Forelli" , true ],
[105, "Donald Love" , true ],
[106, "Donald Love" , true ],
[105, "Donald Love 1" , true ],
[106, "Donald Love 2" , true ],
[107, "Luigi Goterelli" , true ],
[108, "Maria Latore" , true ],
[109, "Mickey Hamfists" , true ],
[110, "Miguel" , true ],
[111, "Misty" , true ],
[112, "Old Oriental Gentleman" , true ],
[113, "Old Oriental Gentleman" , true ],
[114, "Old Oriental Gentleman" , true ],
[112, "Old Oriental Gentleman 1" , true ],
[113, "Old Oriental Gentleman 2" , true ],
[114, "Old Oriental Gentleman 3" , true ],
[115, "Ray Machowski" , true ],
[116, "Mafia Member" , true ],
[117, "Ammunation Clerk" , true ],
[118, "Tanner" , true ],
[119, "Toni Cipriani" , true ],
[120, "Darkel" , true ],
[121, "Chuff Security Officer" , false],
[122, "Claude Speed (Prison)" , false],
[123, "Busker 1" , false],
[124, "Busker 2" , false],
[125, "Busker 3" , false],
[125, "Busker 4" , false],
],
[VRR_GAME_GTA_VC]: [
[0 , "Tommy Vercetti" , false],
@@ -696,104 +702,104 @@ let gameData = {
[5 , "Paramedic" , false],
[6 , "Fireman" , false],
[7 , "Golfer" , true ],
[9 , "Random Lady" , true],
[10 , "Bum" , true],
[9 , "Random Lady 1" , true],
[10 , "Bum 1" , true],
[11 , "Greaser" , true],
[12 , "Random Guy" , true],
[13 , "Random Guy" , true],
[12 , "Random Guy 1" , true],
[13 , "Random Guy 2" , true],
[14 , "Random Lady" , true],
[15 , "Random Guy" , true],
[16 , "Random Guy" , true],
[17 , "Beach Girl" , true],
[15 , "Random Guy 3" , true],
[16 , "Random Guy 4" , true],
[17 , "Beach Lady 1" , true],
[18 , "Fat Beach Lady" , true ],
[19 , "Beach Guy" , true ],
[19 , "Beach Guy 1" , true ],
[20 , "Fat Beach Guy" , true ],
[21 , "Random Lady" , true ],
[22 , "Random Lady" , true ],
[23 , "Random Lady" , true ],
[24 , "Prostitute" , true ],
[25 , "Bum" , true ],
[26 , "Bum" , true ],
[21 , "Random Lady 2" , true ],
[22 , "Random Lady 3" , true ],
[23 , "Random Lady 4" , true ],
[24 , "Prostitute 1" , true ],
[25 , "Bum 2" , true ],
[26 , "Bum 3" , true ],
[27 , "Random Guy" , true ],
[28 , "Taxi Driver" , true ],
[28 , "Taxi Driver 1" , true ],
[29 , "Haitian" , true ],
[30 , "Criminal" , true ],
[31 , "Random Lady" , true ],
[32 , "Random Lady" , true ],
[33 , "Random Guy" , true ],
[34 , "Random Guy" , true ],
[35 , "Random Lady" , true ],
[36 , "Random Lady" , true ],
[37 , "Random Guy" , true ],
[38 , "Beach Lady" , true ],
[39 , "Beach Guy" , true ],
[40 , "Beach Lady" , true ],
[41 , "Beach Guy" , true ],
[42 , "Random Guy" , true ],
[43 , "Prostitute" , true ],
[44 , "Bum" , true ],
[45 , "Bum" , true ],
[46 , "Random Guy" , true ],
[47 , "Random Guy" , true ],
[48 , "Punk" , true ],
[49 , "Prostitute" , true ],
[31 , "Random Lady 5" , true ],
[32 , "Random Lady 6" , true ],
[33 , "Random Guy 5" , true ],
[34 , "Random Guy 6" , true ],
[35 , "Random Lady 7" , true ],
[36 , "Random Lady 8" , true ],
[37 , "Random Guy 7" , true ],
[38 , "Beach Lady 2" , true ],
[39 , "Beach Guy 2" , true ],
[40 , "Beach Lady 3" , true ],
[41 , "Beach Guy 3" , true ],
[42 , "Random Guy 8" , true ],
[43 , "Prostitute 2" , true ],
[44 , "Bum 4" , true ],
[45 , "Bum 5" , true ],
[46 , "Random Guy 9" , true ],
[47 , "Random Guy 9" , true ],
[48 , "Punk 1" , true ],
[49 , "Prostitute 3" , true ],
[50 , "Random Old Lady" , true ],
[51 , "Punk" , true ],
[52 , "Random Guy" , true ],
[53 , "Random Lady" , true ],
[54 , "Random Lady" , true ],
[55 , "Random Guy" , true ],
[56 , "Random Guy" , true ],
[51 , "Punk 2" , true ],
[52 , "Random Guy 10" , true ],
[53 , "Random Lady 9" , true ],
[54 , "Random Lady 10" , true ],
[55 , "Random Guy 11" , true ],
[56 , "Random Guy 12" , true ],
[57 , "Beach Lady" , true ],
[58 , "Beach Guy" , true ],
[58 , "Beach Guy 13" , true ],
[59 , "Beach Lady" , true ],
[60 , "Beach Guy" , true ],
[60 , "Beach Guy 14" , true ],
[61 , "Construction Worker" , true ],
[62 , "Golfer" , true ],
[63 , "Golfer" , true ],
[64 , "Golfer" , true ],
[65 , "Beach Lady" , true ],
[66 , "Beach Guy" , true ],
[67 , "Random Lady" , true ],
[68 , "Random Guy" , true ],
[69 , "Random Guy" , true ],
[70 , "Prostitute" , true ],
[62 , "Golfer 1" , true ],
[63 , "Golfer 2" , true ],
[64 , "Golfer 3" , true ],
[65 , "Beach Lady 4" , true ],
[66 , "Beach Guy 4" , true ],
[67 , "Random Lady 11" , true ],
[68 , "Random Guy 15" , true ],
[69 , "Random Guy 16" , true ],
[70 , "Prostitute 4" , true ],
[71 , "Bum Lady" , true ],
[72 , "Random Guy" , true ],
[73 , "Random Guy" , true ],
[74 , "Taxi Driver" , true ],
[72 , "Random Guy 17" , true ],
[73 , "Random Guy 18" , true ],
[74 , "Taxi Driver 2" , true ],
[75 , "Random Woman" , true ],
[76 , "Skater Guy" , true ],
[77 , "Beach Lady" , true ],
[78 , "Skater Guy" , true ],
[76 , "Skater Guy 1" , true ],
[77 , "Beach Lady 5" , true ],
[78 , "Skater Guy 2" , true ],
[79 , "Young Woman Shopper" , true ],
[80 , "Old Women Shopper" , true ],
[81 , "Tourist" , true ],
[82 , "Tourist" , true ],
[83 , "Cuban" , true ],
[84 , "Cuban" , true ],
[85 , "Haitian" , true ],
[86 , "Haitian" , true ],
[87 , "Shark" , true ],
[88 , "Shark" , true ],
[89 , "Diaz Guy" , true ],
[90 , "Diaz Guy" , true ],
[91 , "Security Guard" , false],
[92 , "Security Guard" , false],
[93 , "Biker" , true ],
[94 , "Biker" , true ],
[95 , "Vercetti Guy" , true ],
[96 , "Vercetti Guy" , true ],
[97 , "Undercover Cop" , false],
[98 , "Undercover Cop" , false],
[99 , "Undercover Cop" , false],
[100, "Undercover Cop " , false],
[101, "Undercover Cop" , false],
[102, "Undercover Cop" , false],
[81 , "Tourist 1" , true ],
[82 , "Tourist 2" , true ],
[83 , "Cuban 1" , true ],
[84 , "Cuban 2" , true ],
[85 , "Haitian 1" , true ],
[86 , "Haitian 2" , true ],
[87 , "Shark 1" , true ],
[88 , "Shark 2" , true ],
[89 , "Diaz Guy 1" , true ],
[90 , "Diaz Guy 2" , true ],
[91 , "Security Guard 1" , false],
[92 , "Security Guard 2" , false],
[93 , "Biker 1" , true ],
[94 , "Biker 2" , true ],
[95 , "Vercetti Guy 1" , true ],
[96 , "Vercetti Guy 2" , true ],
[97 , "Undercover Cop 1" , false],
[98 , "Undercover Cop 2" , false],
[99 , "Undercover Cop 3" , false],
[100, "Undercover Cop 4" , false],
[101, "Undercover Cop 5" , false],
[102, "Undercover Cop 6" , false],
[103, "Random Guy" , true ],
[104, "Bodyguard" , true ],
[105, "Prostitute" , true ],
[106, "Prostitute" , false],
[105, "Prostitute 1" , true ],
[106, "Prostitute 2" , false],
[107, "Ricardo Diaz" , true ],
[108, "Love Fist Guy" , true ],
[109, "Ken Rosenburg" , true ],
@@ -814,39 +820,39 @@ let gameData = {
[124, "Columbian" , true ],
[125, "Hilary" , true ],
[126, "Mercedes" , true ],
[127, "Cam" , true ],
[128, "Cam" , true ],
[129, "Phil" , true ],
[130, "Phil" , true ],
[127, "Cam 1" , true ],
[128, "Cam 2" , true ],
[129, "Phil 1" , true ],
[130, "Phil 2" , true ],
[131, "Bodyguard" , true ],
[132, "Pizza Worker" , true ],
[133, "Taxi Driver" , true ],
[134, "Taxi Driver" , true ],
[135, "Sailor" , true ],
[136, "Sailor" , true ],
[137, "Sailor" , true ],
[133, "Taxi Driver 3" , true ],
[134, "Taxi Driver 4" , true ],
[135, "Sailor 1" , true ],
[136, "Sailor 2" , true ],
[137, "Sailor 3" , true ],
[138, "Chef" , true ],
[139, "Criminal" , true ],
//[140, "French Guy" , true ],
//[141, "Worker" , true ],
[142, "Haitian" , true ],
[143, "Waitress" , true ],
[144, "Forelli Member" , true ],
[145, "Forelli Member" , true ],
[146, "Forelli Member" , true ],
[144, "Forelli Member 1" , true ],
[145, "Forelli Member 2" , true ],
[146, "Forelli Member 3" , true ],
[147, "Columbian" , true ],
[148, "Random Guy" , true ],
[148, "Random Guy 19" , true ],
[149, "Beach Guy" , true ],
[150, "Random Guy" , true ],
[151, "Random Guy" , true ],
[152, "Random Guy" , true ],
[150, "Random Guy 20" , true ],
[151, "Random Guy 21" , true ],
[152, "Random Guy 22" , true ],
[153, "Drag Queen" , true ],
[154, "Diaz Traitor" , true ],
[155, "Random Guy" , true ],
[156, "Random Guy" , true ],
[157, "Stripper" , true ],
[158, "Stripper" , true ],
[159, "Stripper" , true ],
[155, "Random Guy 23" , true ],
[156, "Random Guy 24" , true ],
[157, "Stripper 1" , true ],
[158, "Stripper 2" , true ],
[159, "Stripper 3" , true ],
[160, "Store Clerk" , true ],
[161, "Tommy Vercetti" , true ],
[162, "Tommy Vercetti (Business Suit)" , true ],
@@ -859,22 +865,22 @@ let gameData = {
[169, "Tommy Vercetti (Striped Suit)" , true ],
[170, "Tommy Vercetti (Black Tracksuit)" , true ],
[171, "Tommy Vercetti (Red Tracksuit)" , true ],
[172, "Club Bouncer" , true ],
[173, "Club Bouncer" , true ],
[174, "Stripclub Dancer" , true ],
[175, "Random Guy" , true ],
[176, "Stripclub Dancer" , true ],
[177, "Stripclub Dancer" , true ],
[178, "Stripclub Dancer" , true ],
[179, "Gang Member" , true ],
[172, "Club Bouncer 1" , true ],
[173, "Club Bouncer 2" , true ],
[174, "Stripclub Dancer 1" , true ],
[175, "Random Guy 25" , true ],
[176, "Stripclub Dancer 2" , true ],
[177, "Stripclub Dancer 3" , true ],
[178, "Stripclub Dancer 4" , true ],
[179, "Gang Member 1" , true ],
[180, "Tommy Vercetti (Endgame T-Shirt)" , true ],
[181, "Forelli Thug" , true ],
[182, "Forelli Thug" , true ],
[183, "Random Lady" , true ],
[184, "Gang Member" , true ],
[181, "Forelli Thug 1" , true ],
[182, "Forelli Thug 2" , true ],
[183, "Random Lady 12" , true ],
[184, "Gang Member 2" , true ],
[185, "Party Waitress" , true ],
[186, "Kent Paul" , true ],
[187, "Big Head Taxi Driver" , true ],
[187, "Big Head Taxi Driver" , false ],
],
[VRR_GAME_GTA_SA]: [
[0 , "Carl 'CJ' Johnson" , false],
@@ -5721,6 +5727,7 @@ let gameData = {
ConcertHall: [toVector3(-925.417, 1053.4, 13.2005), 8, false, -1],
RecordingStudio: [toVector3(-879.767, 1156.88, 17.8115), 9, false, -1],
PrintWorks: [toVector3(-1064.98, -279.093, 12.0882), 18, false, -1],
Gas: [toVector3(447.26, 789.09, 12.95), 0, false, -1],
},
[VRR_GAME_GTA_SA]: { // GTA SA
@@ -6244,201 +6251,201 @@ let gameData = {
1208856469
],
},
vehicleUpgrades: {
[VRR_GAME_GTA_SA]: { // GTA SA
1000: "Pro Spoiler",
1001: "Win Spoiler",
1002: "Drag Spoiler",
1003: "Alpha Spoiler",
1004: "Champ Scoop Hood",
1005: "Fury Scoop Hood",
1006: "Roof Scoop Roof",
1007: "Right Sideskirt",
1008: "5x Nitro",
1009: "2x Nitro",
1010: "10x Nitro",
1011: "Race Scoop Hood",
1012: "Worx Scoop Hood",
1013: "Round Fog Lamps",
1014: "Champ Spoiler",
1015: "Race Spoiler",
1016: "Worx Spoiler",
1017: "Left Sideskirt",
1018: "Upswept Exhaust",
1019: "Twin Exhaust",
1020: "Large Exhaust",
1021: "Medium Exhaust",
1022: "Small Exhaust",
1023: "Fury Spoiler",
1024: "Square Fog Lamps",
1025: "Offroad Wheels",
1026: "Right Alien Sideskirt",
1027: "Left Alien Sideskirt",
1028: "Alien Exhaust",
1029: "X-Flow Exhaust",
1030: "Left X-Flow Sideskirt",
1031: "Right X-Flow Sideskirt",
1032: "Alien Roof Vent Roof",
1033: "X-Flow Roof Vent Roof",
1034: "Alien Exhaust",
1035: "X-Flow Roof Vent Roof",
1036: "Right Alien Sideskirt",
1037: "X-Flow Exhaust",
1038: "Alien Roof Vent Roof",
1039: "Left X-Flow Sideskirt",
1040: "Left Alien Sideskirt",
1041: "Right X-Flow Sideskirt",
1042: "Right Chrome Sideskirt",
1043: "Slamin Exhaust",
1044: "Chrome Exhaust",
1045: "X-Flow Exhaust",
1046: "Alien Exhaust",
1047: "Right Alien Sideskirt",
1048: "Right X-Flow Sideskirt",
1049: "Alien Spoiler",
1050: "X-Flow Spoiler",
1051: "Left Alien Sideskirt",
1052: "Left X-Flow Sideskirt",
1053: "X-Flow Roof",
1054: "Alien Roof",
1055: "Alien Roof",
1056: "Right Alien Sideskirt",
1057: "Right X-Flow Sideskirt",
1058: "Alien Spoiler",
1059: "X-Flow Exhaust",
1060: "X-Flow Spoiler",
1061: "X-Flow Roof",
1062: "Left Alien Sideskirt",
1063: "Left X-Flow Sideskirt",
1064: "Alien Exhaust",
1065: "Alien Exhaust",
1066: "X-Flow Exhaust",
1067: "Alien Roof",
1068: "X-Flow Roof",
1069: "Right Alien Sideskirt",
1070: "Right X-Flow Sideskirt",
1071: "Left Alien Sideskirt",
1072: "Left X-Flow Sideskirt",
1073: "Shadow Wheels",
1074: "Mega Wheels",
1075: "Rimshine Wheels",
1076: "Wires Wheels",
1077: "Classic Wheels",
1078: "Twist Wheels",
1079: "Cutter Wheels",
1080: "Switch Wheels",
1081: "Grove Wheels",
1082: "Import Wheels",
1083: "Dollar Wheels",
1084: "Trance Wheels",
1085: "Atomic Wheels",
1086: "Stereo Stereo",
1087: "Hydraulics Hydraulics",
1088: "Alien Roof",
1089: "X-Flow Exhaust",
1090: "Right Alien Sideskirt",
1091: "X-Flow Roof",
1092: "Alien Exhaust",
1093: "Right X-Flow Sideskirt",
1094: "Left Alien Sideskirt",
1095: "Right X-Flow Sideskirt",
1096: "Ahab Wheels",
1097: "Virtual Wheels",
1098: "Access Wheels",
1099: "Left Chrome Sideskirt",
1100: "Chrome Grill Bullbar",
1101: "Left Chrome Flames Sideskirt",
1102: "Left Chrome Strip Sideskirt",
1103: "Covertible Roof",
1104: "Chrome Exhaust",
1105: "Slamin Exhaust",
1106: "Right Chrome Arches Sideskirt",
1107: "Left Chrome Strip Sideskirt",
1108: "Right Chrome Strip Sideskirt",
1109: "Chrome Rear Bullbars",
1110: "Slamin Rear Bullbars",
1113: "Chrome Exhaust",
1114: "Slamin Exhaust",
1115: "Chrome Front Bullbars",
1116: "Slamin Front Bullbars",
1117: "Chrome Front Bumper",
1118: "Right Chrome Trim Sideskirt",
1119: "Right Wheelcovers Sideskirt",
1120: "Left Chrome Trim Sideskirt",
1121: "Left Wheelcovers Sideskirt",
1122: "Right Chrome Flames Sideskirt",
1123: "Chrome Bars Bullbars",
1124: "Left Chrome Arches Sideskirt",
1125: "Chrome Lights Bullbars",
1126: "Chrome Exhaust Exhaust",
1127: "Slamin Exhaust Exhaust",
1128: "Vinyl Hardtop Roof",
1129: "Chrome Exhaust",
1130: "Hardtop Roof",
1131: "Softtop Roof",
1132: "Slamin Exhaust",
1133: "Right Chrome Strip Sideskirt",
1134: "Right Chrome Strip Sideskirt",
1135: "Slamin Exhaust",
1136: "Chrome Exhaust",
1137: "Left Chrome Strip Sideskirt",
1138: "Alien Spoiler",
1139: "X-Flow Spoiler",
1140: "X-Flow Rear Bumper",
1141: "Alien Rear Bumper",
1142: "Left Oval Vents Vents",
1143: "Right Oval Vents Vents",
1144: "Left Square Vents Vents",
1145: "Right Square Vents Vents",
1146: "X-Flow Spoiler",
1147: "Alien Spoiler",
1148: "X-Flow Rear Bumper",
1149: "Alien Rear Bumper",
1150: "Alien Rear Bumper",
1151: "X-Flow Rear Bumper",
1152: "X-Flow Front Bumper",
1153: "Alien Front Bumper",
1154: "Alien Rear Bumper",
1155: "Alien Front Bumper",
1156: "X-Flow Rear Bumper",
1157: "X-Flow Front Bumper",
1158: "X-Flow Spoiler",
1159: "Alien Rear Bumper",
1160: "Alien Front Bumper",
1161: "X-Flow Rear Bumper",
1162: "Alien Spoiler",
1163: "X-Flow Spoiler",
1164: "Alien Spoiler",
1165: "X-Flow Front Bumper",
1166: "Alien Front Bumper",
1167: "X-Flow Rear Bumper",
1168: "Alien Rear Bumper",
1169: "Alien Front Bumper",
1170: "X-Flow Front Bumper",
1171: "Alien Front Bumper",
1172: "X-Flow Front Bumper",
1173: "X-Flow Front Bumper",
1174: "Chrome Front Bumper",
1175: "Slamin Rear Bumper",
1176: "Chrome Front Bumper",
1177: "Slamin Rear Bumper",
1178: "Slamin Rear Bumper",
1179: "Chrome Front Bumper",
1180: "Chrome Rear Bumper",
1181: "Slamin Front Bumper",
1182: "Chrome Front Bumper",
1183: "Slamin Rear Bumper",
1184: "Chrome Rear Bumper",
1185: "Slamin Front Bumper",
1186: "Slamin Rear Bumper",
1187: "Chrome Rear Bumper",
1188: "Slamin Front Bumper",
1189: "Chrome Front Bumper",
1190: "Slamin Front Bumper",
1191: "Chrome Front Bumper",
1192: "Chrome Rear Bumper",
1193: "Slamin Rear Bumper"
},
vehicleComponents: {
[VRR_GAME_GTA_SA]: [ // GTA SA
[1000, "Pro Spoiler"],
[1001, "Win Spoiler"],
[1002, "Drag Spoiler"],
[1003, "Alpha Spoiler"],
[1004, "Champ Scoop Hood"],
[1005, "Fury Scoop Hood"],
[1006, "Roof Scoop Roof"],
[1007, "Right Sideskirt"],
[1008, "5x Nitro"],
[1009, "2x Nitro"],
[1010, "10x Nitro"],
[1011, "Race Scoop Hood"],
[1012, "Worx Scoop Hood"],
[1013, "Round Fog Lamps"],
[1014, "Champ Spoiler"],
[1015, "Race Spoiler"],
[1016, "Worx Spoiler"],
[1017, "Left Sideskirt"],
[1018, "Upswept Exhaust"],
[1019, "Twin Exhaust"],
[1020, "Large Exhaust"],
[1021, "Medium Exhaust"],
[1022, "Small Exhaust"],
[1023, "Fury Spoiler"],
[1024, "Square Fog Lamps"],
[1025, "Offroad Wheels"],
[1026, "Right Alien Sideskirt"],
[1027, "Left Alien Sideskirt"],
[1028, "Alien Exhaust"],
[1029, "X-Flow Exhaust"],
[1030, "Left X-Flow Sideskirt"],
[1031, "Right X-Flow Sideskirt"],
[1032, "Alien Roof Vent Roof"],
[1033, "X-Flow Roof Vent Roof"],
[1034, "Alien Exhaust"],
[1035, "X-Flow Roof Vent Roof"],
[1036, "Right Alien Sideskirt"],
[1037, "X-Flow Exhaust"],
[1038, "Alien Roof Vent Roof"],
[1039, "Left X-Flow Sideskirt"],
[1040, "Left Alien Sideskirt"],
[1041, "Right X-Flow Sideskirt"],
[1042, "Right Chrome Sideskirt"],
[1043, "Slamin Exhaust"],
[1044, "Chrome Exhaust"],
[1045, "X-Flow Exhaust"],
[1046, "Alien Exhaust"],
[1047, "Right Alien Sideskirt"],
[1048, "Right X-Flow Sideskirt"],
[1049, "Alien Spoiler"],
[1050, "X-Flow Spoiler"],
[1051, "Left Alien Sideskirt"],
[1052, "Left X-Flow Sideskirt"],
[1053, "X-Flow Roof"],
[1054, "Alien Roof"],
[1055, "Alien Roof"],
[1056, "Right Alien Sideskirt"],
[1057, "Right X-Flow Sideskirt"],
[1058, "Alien Spoiler"],
[1059, "X-Flow Exhaust"],
[1060, "X-Flow Spoiler"],
[1061, "X-Flow Roof"],
[1062, "Left Alien Sideskirt"],
[1063, "Left X-Flow Sideskirt"],
[1064, "Alien Exhaust"],
[1065, "Alien Exhaust"],
[1066, "X-Flow Exhaust"],
[1067, "Alien Roof"],
[1068, "X-Flow Roof"],
[1069, "Right Alien Sideskirt"],
[1070, "Right X-Flow Sideskirt"],
[1071, "Left Alien Sideskirt"],
[1072, "Left X-Flow Sideskirt"],
[1073, "Shadow Wheels"],
[1074, "Mega Wheels"],
[1075, "Rimshine Wheels"],
[1076, "Wires Wheels"],
[1077, "Classic Wheels"],
[1078, "Twist Wheels"],
[1079, "Cutter Wheels"],
[1080, "Switch Wheels"],
[1081, "Grove Wheels"],
[1082, "Import Wheels"],
[1083, "Dollar Wheels"],
[1084, "Trance Wheels"],
[1085, "Atomic Wheels"],
[1086, "Stereo Stereo"],
[1087, "Hydraulics Hydraulics"],
[1088, "Alien Roof"],
[1089, "X-Flow Exhaust"],
[1090, "Right Alien Sideskirt"],
[1091, "X-Flow Roof"],
[1092, "Alien Exhaust"],
[1093, "Right X-Flow Sideskirt"],
[1094, "Left Alien Sideskirt"],
[1095, "Right X-Flow Sideskirt"],
[1096, "Ahab Wheels"],
[1097, "Virtual Wheels"],
[1098, "Access Wheels"],
[1099, "Left Chrome Sideskirt"],
[1100, "Chrome Grill Bullbar"],
[1101, "Left Chrome Flames Sideskirt"],
[1102, "Left Chrome Strip Sideskirt"],
[1103, "Covertible Roof"],
[1104, "Chrome Exhaust"],
[1105, "Slamin Exhaust"],
[1106, "Right Chrome Arches Sideskirt"],
[1107, "Left Chrome Strip Sideskirt"],
[1108, "Right Chrome Strip Sideskirt"],
[1109, "Chrome Rear Bullbars"],
[1110, "Slamin Rear Bullbars"],
[1113, "Chrome Exhaust"],
[1114, "Slamin Exhaust"],
[1115, "Chrome Front Bullbars"],
[1116, "Slamin Front Bullbars"],
[1117, "Chrome Front Bumper"],
[1118, "Right Chrome Trim Sideskirt"],
[1119, "Right Wheelcovers Sideskirt"],
[1120, "Left Chrome Trim Sideskirt"],
[1121, "Left Wheelcovers Sideskirt"],
[1122, "Right Chrome Flames Sideskirt"],
[1123, "Chrome Bars Bullbars"],
[1124, "Left Chrome Arches Sideskirt"],
[1125, "Chrome Lights Bullbars"],
[1126, "Chrome Exhaust Exhaust"],
[1127, "Slamin Exhaust Exhaust"],
[1128, "Vinyl Hardtop Roof"],
[1129, "Chrome Exhaust"],
[1130, "Hardtop Roof"],
[1131, "Softtop Roof"],
[1132, "Slamin Exhaust"],
[1133, "Right Chrome Strip Sideskirt"],
[1134, "Right Chrome Strip Sideskirt"],
[1135, "Slamin Exhaust"],
[1136, "Chrome Exhaust"],
[1137, "Left Chrome Strip Sideskirt"],
[1138, "Alien Spoiler"],
[1139, "X-Flow Spoiler"],
[1140, "X-Flow Rear Bumper"],
[1141, "Alien Rear Bumper"],
[1142, "Left Oval Vents Vents"],
[1143, "Right Oval Vents Vents"],
[1144, "Left Square Vents Vents"],
[1145, "Right Square Vents Vents"],
[1146, "X-Flow Spoiler"],
[1147, "Alien Spoiler"],
[1148, "X-Flow Rear Bumper"],
[1149, "Alien Rear Bumper"],
[1150, "Alien Rear Bumper"],
[1151, "X-Flow Rear Bumper"],
[1152, "X-Flow Front Bumper"],
[1153, "Alien Front Bumper"],
[1154, "Alien Rear Bumper"],
[1155, "Alien Front Bumper"],
[1156, "X-Flow Rear Bumper"],
[1157, "X-Flow Front Bumper"],
[1158, "X-Flow Spoiler"],
[1159, "Alien Rear Bumper"],
[1160, "Alien Front Bumper"],
[1161, "X-Flow Rear Bumper"],
[1162, "Alien Spoiler"],
[1163, "X-Flow Spoiler"],
[1164, "Alien Spoiler"],
[1165, "X-Flow Front Bumper"],
[1166, "Alien Front Bumper"],
[1167, "X-Flow Rear Bumper"],
[1168, "Alien Rear Bumper"],
[1169, "Alien Front Bumper"],
[1170, "X-Flow Front Bumper"],
[1171, "Alien Front Bumper"],
[1172, "X-Flow Front Bumper"],
[1173, "X-Flow Front Bumper"],
[1174, "Chrome Front Bumper"],
[1175, "Slamin Rear Bumper"],
[1176, "Chrome Front Bumper"],
[1177, "Slamin Rear Bumper"],
[1178, "Slamin Rear Bumper"],
[1179, "Chrome Front Bumper"],
[1180, "Chrome Rear Bumper"],
[1181, "Slamin Front Bumper"],
[1182, "Chrome Front Bumper"],
[1183, "Slamin Rear Bumper"],
[1184, "Chrome Rear Bumper"],
[1185, "Slamin Front Bumper"],
[1186, "Slamin Rear Bumper"],
[1187, "Chrome Rear Bumper"],
[1188, "Slamin Front Bumper"],
[1189, "Chrome Front Bumper"],
[1190, "Slamin Front Bumper"],
[1191, "Chrome Front Bumper"],
[1192, "Chrome Rear Bumper"],
[1193, "Slamin Rear Bumper"],
]
},
fishingLocations: {
[VRR_GAME_GTA_SA]: [ // GTA San Andreas
@@ -6608,6 +6615,27 @@ let gameData = {
[VRR_GAME_MAFIA_THREE]: 0, // Mafia 3
[VRR_GAME_MAFIA_ONE_DE]: 0, // Mafia Definitive Edition
},
properties: {
[VRR_GAME_GTA_VC]: {
ApartmentBuilding1: {
businesses: [
["Manager's Office", 0, 0, toVector3(217.12, -1271.71, 12.09), toVector3(115.48, -823.76, 10.463), 6, null],
],
houses: [
["Apartment 101", 0, 200, toVector3(212.33, -1288.79, 19.27), toVector3(26.67, -1328.89, 13.00), 11, null],
["Apartment 102", 0, 200, toVector3(214.12, -1281.61, 19.27), toVector3(26.67, -1328.89, 13.00), 11, null],
["Apartment 103", 0, 200, toVector3(218.84, -1275.62, 19.27), toVector3(26.67, -1328.89, 13.00), 11, null],
["Apartment 104", 0, 200, toVector3(225.40, -1279.77, 19.27), toVector3(26.67, -1328.89, 13.00), 11, null],
["Apartment 105", 0, 200, toVector3(218.24, -1277.98, 19.27), toVector3(26.67, -1328.89, 13.00), 11, null],
["Apartment 106", 0, 200, toVector3(209.08, -1275.73, 19.27), toVector3(26.67, -1328.89, 13.00), 11, null],
["Apartment 107", 0, 200, toVector3(209.76, -1273.40, 19.27), toVector3(26.67, -1328.89, 13.00), 11, null],
],
npcs: [
["Front Desk Clerk", 160, toVector(215.11, -1272.65, 12.09), 2.95],
]
}
}
}
};
// ===========================================================================