/* ██╗░░░██╗████████╗██╗██╗░░░░░░██████╗ ██║░░░██║╚══██╔══╝██║██║░░░░░██╔════╝ ██║░░░██║░░░██║░░░██║██║░░░░░╚█████╗░ ██║░░░██║░░░██║░░░██║██║░░░░░░╚═══██╗ ╚██████╔╝░░░██║░░░██║███████╗██████╔╝ ░╚═════╝░░░░╚═╝░░░╚═╝╚══════╝╚═════╝░ */ const resName = GetParentResourceName(); const allJobsStatisticsDiv = document.getElementById('all-jobs-statistics').getContext('2d'); const jobStatisticsDiv = document.getElementById('job-statistics-chart').getContext('2d'); let TRANSLATIONS = {}; let ENGLISH_TRANSLATIONS = {}; let MARKERS_INFOS = {}; let ACTIONS_LABELS = {}; function translateEverything() { $("body").find("[data-translation-id], [data-bs-toggle='tooltip']").each(function() { let translationId = $(this).data("translationId") if( $(this).data("bsToggle") == "tooltip" ) { if ($(this).tooltip) { $(this).tooltip('dispose'); } $(this).attr("data-bs-title", getLocalizedText(translationId)); $(this).tooltip(); } else if( $(this).hasClass("form-control") ) { $(this).attr("placeholder", getLocalizedText(translationId)); } else { $(this).prop("innerHTML", getLocalizedText(translationId)); } }) MARKERS_INFOS = { ["stash"]: { label: getLocalizedText("menu:dynamic:marker_info:stash"), settingsName: getLocalizedText("menu:dynamic:marker_info:stash_settings"), isJobMarker: true, isPublicMarker: true, requiresDataUpdate: false }, ["armory"]: { label: getLocalizedText("menu:dynamic:marker_info:armory"), settingsName: getLocalizedText("menu:dynamic:marker_info:armory_settings"), isJobMarker: true, isPublicMarker: true, requiresDataUpdate: true, framework: "ESX" }, ["safe"]: { label: getLocalizedText("menu:dynamic:marker_info:safe"), settingsName: null, isJobMarker: true, isPublicMarker: true, requiresDataUpdate: false, framework: "ESX" }, ["garage"]: { label: getLocalizedText("menu:dynamic:marker_info:temporary_garage"), settingsName: getLocalizedText("menu:dynamic:marker_info:temporary_garage_settings"), isJobMarker: true, isPublicMarker: true, requiresDataUpdate: true }, ["garage_buyable"]: { label: getLocalizedText("menu:dynamic:marker_info:garage_buyable"), settingsName: getLocalizedText("menu:dynamic:marker_info:garage_buyable_settings"), isJobMarker: true, isPublicMarker: true, requiresDataUpdate: true }, ["garage_owned"]: { label: getLocalizedText("menu:dynamic:marker_info:garage_owned"), settingsName: getLocalizedText("menu:dynamic:marker_info:garage_owned_settings"), isJobMarker: true, isPublicMarker: true, requiresDataUpdate: true }, ["boss"]: { label: getLocalizedText("menu:dynamic:marker_info:boss"), settingsName: getLocalizedText("menu:dynamic:marker_info:boss_settings"), isJobMarker: true, isPublicMarker: false, requiresDataUpdate: true }, ["wardrobe"]: { label: getLocalizedText("menu:dynamic:marker_info:wardrobe"), settingsName: null, isJobMarker: true, isPublicMarker: true, requiresDataUpdate: true }, ["job_outfit"]: { label: getLocalizedText("menu:dynamic:marker_info:job_outfit"), settingsName: getLocalizedText("menu:dynamic:marker_info:job_outfit_settings"), isJobMarker: true, isPublicMarker: true, requiresDataUpdate: true }, ["shop"]: { label: getLocalizedText("menu:dynamic:marker_info:shop"), settingsName: getLocalizedText("menu:dynamic:marker_info:shop_settings"), isJobMarker: true, isPublicMarker: true, requiresDataUpdate: true }, ["market"]: { label: getLocalizedText("menu:dynamic:marker_info:market"), settingsName: getLocalizedText("menu:dynamic:marker_info:market_settings"), isJobMarker: true, isPublicMarker: true, requiresDataUpdate: true }, ["harvest"]: { label: getLocalizedText("menu:dynamic:marker_info:harvest"), settingsName: getLocalizedText("menu:dynamic:marker_info:harvest_settings"), isJobMarker: true, isPublicMarker: true, requiresDataUpdate: true }, ["process"]: { label: getLocalizedText("menu:dynamic:marker_info:process"), settingsName: getLocalizedText("menu:dynamic:marker_info:process_settings"), isJobMarker: true, isPublicMarker: true, requiresDataUpdate: true }, ["crafting_table"]: { label: getLocalizedText("menu:dynamic:marker_info:crafting_table"), settingsName: getLocalizedText("menu:dynamic:marker_info:crafting_table_settings"), isJobMarker: true, isPublicMarker: true, requiresDataUpdate: true }, ["teleport"]: { label: getLocalizedText("menu:dynamic:marker_info:teleport"), settingsName: getLocalizedText("menu:dynamic:marker_info:teleport_settings"), isJobMarker: true, isPublicMarker: true, requiresDataUpdate: true }, ["weapon_upgrader"]: { label: getLocalizedText("menu:dynamic:marker_info:weapon_upgrader"), settingsName: getLocalizedText("menu:dynamic:marker_info:weapon_upgrader_settings"), isJobMarker: true, isPublicMarker: true, requiresDataUpdate: true }, ["duty"]: { label: getLocalizedText("menu:dynamic:marker_info:duty"), settingsName: null, isJobMarker: true, isPublicMarker: false, requiresDataUpdate: true }, ["job_shop"]: { label: getLocalizedText("menu:dynamic:marker_info:job_shop"), settingsName: getLocalizedText("menu:dynamic:marker_info:job_shop_settings"), isJobMarker: false, isPublicMarker: true, requiresDataUpdate: true }, } ACTIONS_LABELS = [ {action: "actionsMenuEnabled", label: getLocalizedText("menu:job_settings:can_open_actions_menu")}, {action: "canRepairVehicles", label: getLocalizedText("menu:job_settings:enable_repair_vehicles")}, {action: "canCheckDrivingLicense", label: getLocalizedText("menu:job_settings:enable_check_driving_license")}, {action: "canCheckWeaponLicense", label: getLocalizedText("menu:job_settings:enable_check_weapon_license")}, {action: "enableBilling", label: getLocalizedText("menu:job_settings:enable_billing")}, {action: "canHandcuff", label: getLocalizedText("menu:job_settings:enable_handcuff_players")}, {action: "placeableObjects", label: getLocalizedText("menu:job_settings:placeable_objects")}, {action: "canLockpickCars", label: getLocalizedText("menu:job_settings:enable_lockpick_players")}, {action: "whitelisted", label: getLocalizedText("menu:job_settings:whitelisted")}, {action: "canRevive", label: getLocalizedText("menu:job_settings:enable_revive")}, {action: "canWashVehicles", label: getLocalizedText("menu:job_settings:enable_wash_vehicles")}, {action: "canRob", label: getLocalizedText("menu:job_settings:enable_search_players")}, {action: "canCheckIdentity", label: getLocalizedText("menu:job_settings:enable_check_identities")}, {action: "canImpoundVehicles", label: getLocalizedText("menu:job_settings:enable_impound_vehicles")}, {action: "canCheckVehicleOwner", label: getLocalizedText("menu:job_settings:enable_check_vehicle_owner")}, {action: "canHeal", label: getLocalizedText("menu:job_settings:enable_heal")}, ] } async function refreshTranslations(locale) { let rawEnglishTranslations = await $.get("menu_translations/en.json"); ENGLISH_TRANSLATIONS = typeof rawEnglishTranslations == "object" ? rawEnglishTranslations : JSON.parse(rawEnglishTranslations); let rawTranslations = await $.get(`menu_translations/${locale}.json`); TRANSLATIONS = typeof rawTranslations == "object" ? rawTranslations : JSON.parse(rawTranslations); translateEverything(); } async function loadTranslations() { const locale = await $.post(`https://${resName}/getLocale`); refreshTranslations(locale); } loadTranslations(); function getLocalizedText(text) { return TRANSLATIONS[text] || ENGLISH_TRANSLATIONS[text] || text; } async function getFramework() { const framework = await $.post(`https://${resName}/getFramework`); return framework; } const allJobsStatisticsChart = new Chart(allJobsStatisticsDiv, { type: 'bar', data: { labels: "Jobs", datasets: [] }, options: { scales: { y: { beginAtZero: true } }, } }); const jobStatisticsChart = new Chart(jobStatisticsDiv, { type: 'bar', data: { labels: "Ranks", datasets: [] }, options: { scales: { y: { beginAtZero: true } }, } }); // Fetch all the forms we want to apply custom Bootstrap validation styles to var forms = document.querySelectorAll('.needs-validation') // Loop over them and prevent submission Array.prototype.slice.call(forms) .forEach(function (form) { form.addEventListener('submit', function (event) { event.preventDefault(); form.classList.add('was-validated') }, false) }) $(".max-two-decimals").change(function() { if(isNaN(this.value)) { return } let number = parseFloat(this.value); if(number) { this.value = number.toFixed(2); } }) function getValidId(text) { text = text.toLowerCase(); text = text.replace(/[^a-zA-Z0-9]/g,'_'); return text } $(".id").on("input", function() { let text = $(this).val(); $(this).val( getValidId(text) ); }) function componentToHex(c) { var hex = c.toString(16); return hex.length == 1 ? "0" + hex : hex; } function rgbToHex(r, g, b) { return "#" + componentToHex(r) + componentToHex(g) + componentToHex(b); } function hexToRgb(hex) { var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); return result ? { r: parseInt(result[1], 16), g: parseInt(result[2], 16), b: parseInt(result[3], 16) } : null; } function getVehicleLabel(vehicleModel, cb) { $.post(`https://${resName}/get-vehicle-label`, JSON.stringify({vehicleModel: vehicleModel}), cb) } // Disables enter $(document).on("keypress", 'form', function (e) { var code = e.keyCode || e.which; if (code == 13) { e.preventDefault(); return false; } }); /* Dialogs */ function inputDialog(title, data, yesCallback) { $("#input-text-dialog-title").text(title); var inputModal = $("#input-text-dialog-modal"); // Removes old data inputModal.find(".modal-body form").empty(); data.forEach(currentData => { var id = currentData.id; var label = currentData.label; var defaultValue = currentData.default !== undefined ? currentData.default : ""; var type = currentData.type || "text"; if (type === "button") { var button = $(``); button.click(function () { currentData.buttonCallback(inputModal); }); inputModal.find(".modal-body form").append(button); } else if (type === "select") { var select = $(``) var options = currentData.options options.forEach(option => { var optionElement = $(``) select.append(optionElement); }) inputModal.find(".modal-body form").append(select); } else if (type === "switch") { var switchInput = $(`
`); inputModal.find(".modal-body form").append(switchInput); $(`#modal-${id}`).prop("checked", defaultValue) } else { let isAnId = currentData.isId || false var formGroup = $( `
Can't be empty
` ) inputModal.find(".modal-body form").append(formGroup) let inputDiv = $(`#modal-${id}`); inputDiv.unbind('input'); if(isAnId) { inputDiv.on('input', function() { let text = inputDiv.val(); text = text.toLowerCase(); text = text.replace(/[^a-zA-Z0-9]/g,'_'); inputDiv.val(text); }); } } }) inputModal.modal("show"); $("#input-text-dialog-confirm").off('click'); $("#input-text-dialog-confirm").click(function () { var areInputsValid = true; var inputs = inputModal.find(".form-control, .form-select, :checkbox"); var length = inputs.length; var data = {}; inputs.each(function (index, element) { var text = $(element).val(); if (text || $(element).is(":checkbox")) { $(element).removeClass("is-invalid"); var id = $(element).data("id"); if ($(element).is(":checkbox")) { data[id] = $(element).is(':checked'); } else { data[id] = text; } } else { $(element).addClass("is-invalid"); areInputsValid = false; } }); inputModal.modal("hide"); yesCallback(data); }) } function showError(msg){ $("#notification-message").text(msg); $("#notification-modal").modal("show"); } function accountsDialog(cb) { let accountsModal = $("#input-accounts-dialog-modal"); let accountsList = $("#accounts-list"); $.post(`https://${resName}/getAllAccounts`, {}, function (accounts) { accountsList.empty(); for(const[accountName, accountLabel] of Object.entries(accounts)) { let accountDiv = $(`
  • ${accountLabel}
  • `); accountDiv.click(function() { accountsModal.modal("hide"); cb(accountName); }); accountsList.append(accountDiv); } accountsModal.modal("show"); }) } async function getCurrentCoordsAndHeading() { return new Promise((resolve, reject) => { $.post(`https://${resName}/get-current-coords`, {}, function (coords) { resolve(coords); }); }); } /* ██████╗░░█████╗░███╗░░██╗██╗░░██╗░██████╗ ██╔══██╗██╔══██╗████╗░██║██║░██╔╝██╔════╝ ██████╔╝███████║██╔██╗██║█████═╝░╚█████╗░ ██╔══██╗██╔══██║██║╚████║██╔═██╗░░╚═══██╗ ██║░░██║██║░░██║██║░╚███║██║░╚██╗██████╔╝ ╚═╝░░╚═╝╚═╝░░╚═╝╚═╝░░╚══╝╚═╝░░╚═╝╚═════╝░ */ let ranksDataTable = $("#ranks-container").DataTable( { "lengthMenu": [5, 10, 15, 20], "pageLength": 10, "createdRow": function ( row, data, index ) { $(row).addClass("clickable"); $(row).click(function() { let editRankModal = $("#edit-rank"); let rankId = data[0]; let rankLabel = data[1]; let rankName = data[2]; let rankGrade = data[3]; let rankSalary = data[4]; $("#edit-rank-label").val(rankLabel); $("#edit-rank-name").val(rankName); $("#edit-rank-grade").val(rankGrade); $("#edit-rank-salary").val(rankSalary); editRankModal.data("rankId", rankId); editRankModal.modal("show"); }) }, "columnDefs": [{"defaultContent": "???", "targets": "_all"}] } ); async function deleteRank(jobName, rankId) { if(! await confirmDeletion(getLocalizedText("menu:do_you_want_to_delete_the_rank"))) return; const data = await $.post(`https://${resName}/delete-rank`, JSON.stringify({ rankId: rankId })); // Removes deleted row if (data.isSuccessful) { refreshJobRanks(jobName) } else { showError(data.message) } } function fillJobRanks(ranks) { ranksDataTable.clear(); for(const[_, gradeData] of Object.entries(ranks)) { ranksDataTable.row.add( [gradeData.id, gradeData.label, gradeData.name, gradeData.grade, gradeData.salary] ); } ranksDataTable.draw(); } $("#edit-rank-form").submit(function(event) { if (!this.checkValidity()) { event.preventDefault(); event.stopPropagation(); return; } else { $(this).removeClass("was-validated"); $("#create-rank").modal("hide"); } let data = { rankLabel: $("#edit-rank-label").val(), rankName: $("#edit-rank-name").val(), rankGrade: parseInt( $("#edit-rank-grade").val() ), rankSalary: parseInt( $("#edit-rank-salary").val() ), rankId: $("#edit-rank").data("rankId") } $.post(`https://${resName}/updateRank`, JSON.stringify(data), function (resultData) { // Updates old row field with new values if (resultData.isSuccessful) { refreshJobRanks( $("#edit-job").data("jobName") ); } else { showError(resultData.message) } }); $("#edit-rank").modal("hide"); }) $("#edit-rank-delete-btn").click(function() { let jobName = $("#edit-job").data("jobName"); let rankId = $("#edit-rank").data("rankId"); deleteRank(jobName, rankId); }) $("#create-rank-btn").click(function() { // Reset previous inputs $("#create-rank-label").val(""); $("#create-rank-name").val(""); $("#create-rank-grade").val(""); $("#create-rank-salary").val(""); $("#create-rank").modal("show"); }); // Automatically fills the id from the label $("#create-rank-label").on("input", function(){ let label = $(this).val(); let id = getValidId(label); $("#create-rank-name").val(id); }) // Automatically fills the id from the label $("#edit-rank-label").on("input", function(){ let label = $(this).val(); let id = getValidId(label); $("#edit-rank-name").val(id); }) $("#create-rank-form").submit(function(event) { if(isThereAnyErrorInForm(event)) return; let jobName = $("#edit-job").data("jobName"); let data = { rankLabel: $("#create-rank-label").val(), rankName: $("#create-rank-name").val(), rankGrade: parseInt( $("#create-rank-grade").val() ), rankSalary: parseInt( $("#create-rank-salary").val() ), jobName: jobName } $.post(`https://${resName}/create-new-rank`, JSON.stringify(data), function (data) { if (data.isSuccessful) { refreshJobRanks(jobName) } else { showError(data.message) } }); $("#create-rank").modal("hide"); }) function refreshJobRanks(jobName) { $.post(`https://${resName}/retrieveJobRanks`, JSON.stringify({ jobName: jobName }), function (ranks) { if (ranks) { fillJobRanks(ranks) } }); } /* ░░░░░██╗░█████╗░██████╗░░██████╗ ░░░░░██║██╔══██╗██╔══██╗██╔════╝ ░░░░░██║██║░░██║██████╦╝╚█████╗░ ██╗░░██║██║░░██║██╔══██╗░╚═══██╗ ╚█████╔╝╚█████╔╝██████╦╝██████╔╝ ░╚════╝░░╚════╝░╚═════╝░╚═════╝░ */ var allJobs = {}; async function refresh() { fillPublicMarkers(); const jobs = await $.post(`https://${resName}/getJobsData`, {}); allJobs = jobs; fillJobs(jobs); } $("#create-job-btn").click(function () { inputDialog(getLocalizedText("menu:create_new_job"), [ { id: "jobLabel", label: getLocalizedText("menu:dynamic:new_job_label") }, { id: "jobName", label: getLocalizedText("menu:dynamic:new_job_name"), isId: true }, ], function (data) { $.post(`https://${resName}/create-new-job`, JSON.stringify({ jobLabel: data.jobLabel, jobName: data.jobName }), function (data) { if (data.isSuccessful) { refresh() } else { showError(data.message) } }); }); }) function exitFromEditJob(){ // Resets current active tab (ranks is the default one) $("#edit-job").find(".nav-link, .tab-pane").each(function() { if($(this).data("isDefault") == "1") { $(this).addClass(["active", "show"]) } else { $(this).removeClass(["active", "show"]) } }) refresh(); $("#edit-job").hide(); $("#job-creator").show(); } async function deleteJob(jobName) { if(! await confirmDeletion(getLocalizedText("menu:dynamic:delete_job_confirm"))) return; const data = await $.post(`https://${resName}/delete-job`, JSON.stringify({ jobName: jobName })); data.isSuccessful ? exitFromEditJob() : showError(data.message); } $("#delete-job-btn").click(function() { let jobName = $("#edit-job").data("jobName"); deleteJob(jobName); }) $("#edit-job-label").on("input", function(){ let label = $(this).val(); let id = getValidId(label); $("#edit-job-name").val(id); }) function editJob(jobData) { let editJobDiv = $("#edit-job"); editJobDiv.data("jobName", jobData.name); // Chart with ranks loadRanksDistrubutions(); // Job settings $("#edit-job-label").val(jobData.label); $("#edit-job-name").val(jobData.name); // Fills actions in settings if(jobData.actions) { for(const[actionName, isEnabled] of Object.entries(jobData.actions)) { $("#job-settings-actions").find(`[data-action-name=${actionName}]`).prop("checked", isEnabled) } } // Fill placeable objects $("#job-placeable-objects-list").empty(); $("#job-placeable-objects-no-objects-text").show(); // It will be hidden if there are objects for(const [model, objectData] of Object.entries(jobData.actions?.placeableObjects || {})) { addPlaceableObject(model, objectData.label, objectData.limit); } $("#edit-job-text").text(jobData.label); fillJobRanks(jobData.ranks); fillJobMarkers(); $("#job-creator").hide(); editJobDiv.show(); jobTour(); } $("#edit-job-close-btn").click(exitFromEditJob); function addPlaceableObject(model, label, limit) { const div = $(`
    `); div.find(".delete-object-btn").click(function() { div.remove(); if($("#job-placeable-objects-list").children().length == 0) { $("#job-placeable-objects-no-objects-text").show(); } }); div.find(".object-model").val(model || ""); div.find(".object-label").val(label || ""); div.find(".object-limit").val(limit || 1); $("#job-placeable-objects-no-objects-text").hide(); $("#job-placeable-objects-list").append(div); } $("#job-placeable-objects-add-btn").click(function() { addPlaceableObject(); }); $("#job-settings").submit(function(event) { if (!this.checkValidity()) { event.stopPropagation(); event.preventDefault(); return; } else { $(this).removeClass("was-validated"); } let actions = {}; $("#job-settings-actions").find(".job-action").each(function() { let actionName = $(this).data("actionName"); actions[actionName] = $(this).prop("checked"); }) let placeableObjects = {}; $("#job-placeable-objects-list").find(".placeable-object").each(function() { let model = $(this).find(".object-model").val(); placeableObjects[model] = { label: $(this).find(".object-label").val(), limit: parseInt( $(this).find(".object-limit").val() ) } }); actions["placeableObjects"] = placeableObjects; let oldJobName = $("#edit-job").data("jobName"); let jobName = $("#edit-job-name").val(); let jobLabel = $("#edit-job-label").val(); let data = { oldJobName, jobName, jobLabel, actions } $.post(`https://${resName}/update-job`, JSON.stringify(data), function (resultData) { // Updates old job with new values if (resultData.isSuccessful) { exitFromEditJob(); } else { showError(resultData.message) } }); }) let jobsDataTable = $("#jobs-container").DataTable( { "lengthMenu": [5, 10, 15, 20], "pageLength": 10, "createdRow": function ( row, data, index ) { $(row).addClass("clickable"); $(row).click(function() { let jobName = data[1]; editJob(allJobs[jobName]) }) }, "columnDefs": [{"defaultContent": "???", "targets": "_all"}] } ); function fillJobs(jobs) { jobsDataTable.clear(); for (const [_, job] of Object.entries(jobs)) { jobsDataTable.row.add( [job.label, job.name, Object.entries(job.ranks).length] ); } jobsDataTable.draw(); } /* ███╗░░░███╗░█████╗░██████╗░██╗░░██╗███████╗██████╗░░██████╗ ████╗░████║██╔══██╗██╔══██╗██║░██╔╝██╔════╝██╔══██╗██╔════╝ ██╔████╔██║███████║██████╔╝█████═╝░█████╗░░██████╔╝╚█████╗░ ██║╚██╔╝██║██╔══██║██╔══██╗██╔═██╗░██╔══╝░░██╔══██╗░╚═══██╗ ██║░╚═╝░██║██║░░██║██║░░██║██║░╚██╗███████╗██║░░██║██████╔╝ ╚═╝░░░░░╚═╝╚═╝░░╚═╝╚═╝░░╚═╝╚═╝░░╚═╝╚══════╝╚═╝░░╚═╝╚═════╝░ */ let allMarkers = {}; let jobMarkersDataTable = $("#job-markers-container").DataTable( { "lengthMenu": [5, 10, 15, 20], "pageLength": 10, "createdRow": function ( row, data, index ) { $(row).addClass("clickable"); $(row).click(function() { let markerId = data[0]; editMarker(markerId); }) }, "columnDefs": [{"defaultContent": "???", "targets": "_all"}] } ); let publicMarkersDataTable = $("#public-markers-container").DataTable( { "lengthMenu": [5, 10, 15, 20], "pageLength": 10, "createdRow": function ( row, data, index ) { $(row).addClass("clickable"); $(row).click(function() { let markerId = data[0]; editMarker(markerId); }) }, "columnDefs": [{"defaultContent": "???", "targets": "_all"}] } ); function fillJobMarkers(markerToEdit) { let jobName = $("#edit-job").data("jobName"); $.post(`https://${resName}/retrieveJobMarkers`, JSON.stringify({ jobName: jobName }), function (markers) { allMarkers = {}; // Manually insert each marker to avoid wrong conversion between lua table first index (1) and javascript object first index (0) for(const[k, markerData] of Object.entries(markers)) { allMarkers[markerData.id] = markerData; } jobMarkersDataTable.clear(); for(const[_, markerData] of Object.entries(markers)) { let typeLabel = MARKERS_INFOS[markerData.type]?.label; jobMarkersDataTable.row.add( [markerData.id || "Unknown", markerData.label || "No name", typeLabel, markerData.coords.x, markerData.coords.y, markerData.coords.z] ); } jobMarkersDataTable.draw(); if(markerToEdit) { editMarker(markerToEdit); } }) } function fillPublicMarkers(markerToEdit) { $.post(`https://${resName}/retrieveJobMarkers`, JSON.stringify({ jobName: "public_marker" }), function (markers) { allMarkers = {}; // Manually insert each marker to avoid wrong conversion between lua table first index (1) and javascript object first index (0) for(const[k, markerData] of Object.entries(markers)) { allMarkers[markerData.id] = markerData; } publicMarkersDataTable.clear(); for(const[_, markerData] of Object.entries(markers)) { let typeLabel = MARKERS_INFOS[markerData.type]?.label; publicMarkersDataTable.row.add( [markerData.id, markerData.label || "No name", typeLabel, markerData.coords.x, markerData.coords.y, markerData.coords.z] ); } publicMarkersDataTable.draw(); if(markerToEdit) { editMarker(markerToEdit); } }) } function getOffDutyName(name) { return "off_" + name; } function getOnDutyName(name) { return name.replace("off_", ""); } function isOffDutyName(name) { return name.includes("off_"); } async function createJobMarker(jobName) { let allowedMarkers = []; for(const[markerType, markerInfo] of Object.entries(MARKERS_INFOS)) { if(markerInfo.framework != undefined && markerInfo.framework != await getFramework()) continue; if(!markerInfo.isJobMarker) continue; allowedMarkers.push({ value: markerType, label: markerInfo.label }) } inputDialog(getLocalizedText("menu:dynamic:job_markers:create_marker"), [ { id: "markerType", label: "Marker Type:", type: "select", options: allowedMarkers }, { id: "label", label: getLocalizedText("menu:dynamic:job_markers:label"), type: "text", default: getLocalizedText("menu:dynamic:default") }, { id: "markerCoordsX", label: getLocalizedText("menu:dynamic:job_markers:coord_x"), type: "number" }, { id: "markerCoordsY", label: getLocalizedText("menu:dynamic:job_markers:coord_y"), type: "number" }, { id: "markerCoordsZ", label: getLocalizedText("menu:dynamic:job_markers:coord_z"), type: "number" }, { id: "currentCoordsBtn", label: getLocalizedText("menu:dynamic:job_markers:current_coords"), type: "button", buttonType: "btn-success", buttonCallback: async function (modal) { const coords = await placeEntity(); if(!coords) return; modal.find("#modal-markerCoordsX").val(coords.x) modal.find("#modal-markerCoordsY").val(coords.y) modal.find("#modal-markerCoordsZ").val(coords.z) } }, { id: "markerMinGrade", label: getLocalizedText("menu:dynamic:job_markers:min_grade"), type: "number", default: 0 }, ], async function (data) { data.jobName = jobName const resultData = await $.post(`https://${resName}/create-marker`, JSON.stringify(data)); if (resultData.isSuccessful) { fillJobMarkers(resultData.markerId); if(!isOffDutyName(jobName) && await getFramework() == "ESX" && data.markerType == "duty") { const duplicateForOffDuty = await swal({ title: getLocalizedText("menu:note"), text: getLocalizedText("menu:do_you_want_to_create_it_also_for_off_duty_job"), icon: "info", buttons: true, dangerMode: false, }); if(!duplicateForOffDuty) return; data.jobName = getOffDutyName(jobName); const resultData = await $.post(`https://${resName}/create-marker`, JSON.stringify(data)); if (resultData.isSuccessful) { fillJobMarkers(resultData.markerId); } else { showError(resultData.message) } } } else { showError(resultData.message) } }) } $("#create-job-marker-btn").click(function() { let jobName = $("#edit-job").data("jobName"); createJobMarker(jobName); }) async function createPublicMarker() { let allowedMarkers = []; for(const[markerType, markerInfo] of Object.entries(MARKERS_INFOS)) { if(markerInfo.framework == undefined || markerInfo.framework == await getFramework()) { if(markerInfo.isPublicMarker) { allowedMarkers.push({ value: markerType, label: markerInfo.label }) } } } inputDialog(getLocalizedText("menu:dynamic:public_markers:create_public_marker"), [ { id: "markerType", label: "Marker Type:", type: "select", options: allowedMarkers }, { id: "label", label: getLocalizedText("menu:dynamic:public_markers:label"), type: "text", default: getLocalizedText("menu:dynamic:default") }, { id: "markerCoordsX", label: getLocalizedText("menu:dynamic:public_markers:coord_x"), type: "number" }, { id: "markerCoordsY", label: getLocalizedText("menu:dynamic:public_markers:coord_y"), type: "number" }, { id: "markerCoordsZ", label: getLocalizedText("menu:dynamic:public_markers:coord_z"), type: "number" }, { id: "currentCoordsBtn", label: getLocalizedText("menu:dynamic:public_markers:current_coords"), type: "button", buttonType: "btn-success", buttonCallback: async function (modal) { const coords = await placeEntity(); if(!coords) return; modal.find("#modal-markerCoordsX").val(coords.x) modal.find("#modal-markerCoordsY").val(coords.y) modal.find("#modal-markerCoordsZ").val(coords.z) } }, ], function (data) { $.post(`https://${resName}/create-public-marker`, JSON.stringify(data), function (data) { if (data.isSuccessful) { fillPublicMarkers(data.markerId); } else { showError(data.message) } }); }) } $("#create-public-marker-btn").click(createPublicMarker); function hideAllMarkerSettings() { $("#edit-marker-form").find(".edit-marker-settings").each(function() { $(this).find(".form-control").each(function(index, element) { if($(element).prop("required")) { $(element).prop("required", false); $(element).data("isActuallyRequired", true); } }); $(this).hide(); }) } function showMarkerSettings(markerType) { hideAllMarkerSettings(); $("#edit-marker-form").find(`.edit-marker-settings`).each(function() { if( $(this).data("markerType") != markerType ) return; $(this).find(".form-control").each(function(index, element) { if( $(element).data("isActuallyRequired") ) { $(element).prop("required", true); } }); $(this).show(); return; }) } function editMarker(markerId) { $("#edit-marker-form").removeClass("was-validated"); let markerData = allMarkers[markerId]; if(!markerData) { console.log("Couldn't find marker " + markerId); console.log(`Existing markers for job '${ $("#edit-job").data("jobName") }': `) for(const[key, value] of Object.entries(allMarkers)) { console.log(` Marker ID '${key}'`); } return } let isMarkerPublic = markerData.jobName == "public_marker"; $("#edit-marker-form").data("isPublic", isMarkerPublic); $("#edit-marker-label").val(markerData.label); $("#edit-marker-type").val(markerData.markerType); changeMarkerGradeType(markerData.gradesType); if(markerData.gradesType === "specificGrades") { setSpecificGrades(markerData.specificGrades); } else if(markerData.gradesType === "minimumGrade") { $("#edit-marker-min-grade").val(markerData.minGrade); } $("#edit-marker-scale-x").val(markerData.scale.x); $("#edit-marker-scale-y").val(markerData.scale.y); $("#edit-marker-scale-z").val(markerData.scale.z); $("#edit-marker-coord-x").val(markerData.coords.x); $("#edit-marker-coord-y").val(markerData.coords.y); $("#edit-marker-coord-z").val(markerData.coords.z); $("#edit-marker-color").val(rgbToHex(markerData.color.r, markerData.color.g, markerData.color.b)); $("#edit-marker-alpha").val(markerData.color.alpha); // Map blip $("#edit-marker-sprite-id").val(markerData.blip?.spriteId); $("#edit-marker-blip-color").val(markerData.blip?.color); $("#edit-marker-blip-scale").val(markerData.blip?.scale); toggleBlipInputs(markerData.blip?.spriteId ? true : false); // NPC $("#edit-marker-npc-model").val(markerData.ped?.model); $("#edit-marker-npc-heading").val(markerData.ped?.heading); toggleNpcInputs(markerData.ped?.model ? true : false); // Object $("#edit-marker-object-model").val(markerData.object?.model); $("#edit-marker-object-heading").val(markerData.object?.heading); toggleObjectInputs(markerData.object?.model ? true : false); // Minimum grade / specific grade inputs $("#edit-marker-min-grade").prop("disabled", isMarkerPublic); $("input[name=markerGradeType]").prop("disabled", isMarkerPublic); $("#edit-marker-min-grade").val(markerData.minGrade || 0); let settingsLabel = MARKERS_INFOS[markerData.type].settingsName; if(settingsLabel) { $("#specific-marker-settings").show(); $("#specific-marker-settings-label").text(settingsLabel); showMarkerSettings(markerData.type); } else { $("#specific-marker-settings").hide(); hideAllMarkerSettings(); } setCurrentMarkerData(markerData.type, markerData.data); let editMarkerModal = $("#edit-marker-dialog-modal"); editMarkerModal.modal("show"); editMarkerModal.data("markerId", markerId); } function changeMarkerGradeType(type) { $(`input[type=radio][name="markerGradeType"][value="${type}"]`).prop("checked", true); switch(type) { case "minimumGrade": { $("#edit-marker-min-grade").prop("required", true); $("#edit-marker-min-grade-form").show(); $("#edit-marker-specific-grades-form").hide(); break; } case "specificGrades": { $("#edit-marker-min-grade").prop("required", false); $("#edit-marker-min-grade-form").hide(); $("#edit-marker-specific-grades-form").show(); break; } } } $("input[type=radio][name=markerGradeType").change(function() { let gradesType = $(this).val(); changeMarkerGradeType(gradesType); }) function addVehicleToTemporaryGarage(vehicleModel, vehicleData) { vehicleData = vehicleData || {} let vehiclesTable = $("#garage-data-model-tbody") let vehiclePrimaryColor = vehicleData.primaryColor || "#111111" let vehicleSecondaryColor = vehicleData.secondaryColor || "#111111" let livery = vehicleData.livery; let customPlate = vehicleData.plate || ""; let deleteVehicleBtn = $(``) let vehicleTableRow = $(`

    ${vehicleModel}

    ${vehicleModel}

    `) getVehicleLabel(vehicleModel, (vehicleLabel) => { vehicleTableRow.find(".vehicle-label").text(vehicleLabel) }) vehiclesTable.append(vehicleTableRow); vehicleTableRow.find(".delete-vehicle-btn").append(deleteVehicleBtn) $(deleteVehicleBtn).click(function () { $(this).parents(".vehicle").remove(); }); } $("#garage-owned-current-coords").click(function() { $.post(`https://${resName}/get-current-coords`, {}, function (data) { var coords = data.coords; var heading = data.heading; if (coords) { $("#garage-owned-spawnpoint-x").val(coords.x) $("#garage-owned-spawnpoint-y").val(coords.y) $("#garage-owned-spawnpoint-z").val(coords.z) } if (heading) { $("#garage-owned-heading").val(heading) } }) }); function toggleBlipInputs(isEnabled) { $("#edit-marker-map-blip").prop("checked", isEnabled); $("#edit-marker-map-blip-inputs").find(".form-control").each(function() { $(this).prop("disabled", !isEnabled); $(this).prop("required", isEnabled); }) } function toggleNpcInputs(isEnabled) { $("#edit-marker-npc").prop("checked", isEnabled); $("#edit-marker-npc-inputs").find(".form-control").each(function() { $(this).prop("disabled", !isEnabled); $(this).prop("required", isEnabled); }) } function toggleObjectInputs(isEnabled) { $("#edit-marker-object").prop("checked", isEnabled); $("#edit-marker-object-inputs").find(".form-control").each(function() { $(this).prop("disabled", !isEnabled); $(this).prop("required", isEnabled); }) } // Boss marker settings function toggleBossWashMoneyOptions(isEnabled) { $("#boss-data-washmoney-percentage").prop("required", isEnabled); $("#boss-data-washmoney-percentage").prop("disabled", !isEnabled); $("#boss-data-washmoney-to-society-account").prop("disabled", !isEnabled); } $("#boss-data-washmoney").change(function() { toggleBossWashMoneyOptions( $(this).prop("checked") ); }) // Harvestable items settings $("#harvest-item-requires-tool").change(function() { const isEnabled = $(this).prop("checked"); $("#harvest-item-tool-div").find("input, button").prop("required", isEnabled).prop("disabled", !isEnabled); $("#harvest-item-tool-lose-on-use").prop("disabled", !isEnabled); if(!isEnabled) { $("#harvest-item-tool-lose-on-use").prop("checked", false).change(); } }) $("#harvest-item-tool-lose-on-use").change(function() { const isEnabled = $(this).prop("checked"); $("#harvest-item-tool-lose-quantity") .prop("required", isEnabled) .prop("disabled", !isEnabled); $("#harvest-item-tool-lose-probability") .prop("required", isEnabled) .prop("disabled", !isEnabled); }) $("#harvest-disappear-after-use").change(function() { toggleDisappearsAfterUse( $(this).prop("checked") ); $("#harvest-disappear-seconds") .prop("required", isEnabled) .prop("disabled", !isEnabled); }) function toggleDisappearsAfterUse(isEnabled) { $("#harvest-disappear-after-use").prop("checked", isEnabled); $("#harvest-disappear-seconds").prop("required", isEnabled); $("#harvest-disappear-seconds").prop("disabled", !isEnabled); } $("#harvest-requires-minimum-account-money").change(function() { let isEnabled = $(this).prop("checked"); $("#harvest-minimum-account-name-div").find("input, button").prop("disabled", !isEnabled); $("#harvest-minimum-account-name-div").find("input, button").prop("required", isEnabled); }); // Marker generic settings $("#edit-marker-map-blip").change(function(){ let isEnabled = $(this).prop("checked"); toggleBlipInputs(isEnabled); }) $("#edit-marker-npc").change(function(){ let isEnabled = $(this).prop("checked"); toggleNpcInputs(isEnabled); }) $("#edit-marker-object").change(function(){ let isEnabled = $(this).prop("checked"); toggleObjectInputs(isEnabled); }) $("#edit-marker-current-coords-btn").click(async function(){ const npcModel = $("#edit-marker-npc").prop("checked") ? $("#edit-marker-npc-model").val() : null; const objectModel = $("#edit-marker-object") ? $("#edit-marker-object-model").val() : null; if(npcModel) { var data = await placeEntity(npcModel, "ped"); } else if(objectModel) { var data = await placeEntity(objectModel, "object"); } else { var data = await placeEntity(); } if(!data) return; if(npcModel || objectModel) { $("#edit-marker-coord-x").val(data.coords.x) $("#edit-marker-coord-y").val(data.coords.y) $("#edit-marker-coord-z").val(data.coords.z) if(npcModel) $("#edit-marker-npc-heading").val(data.heading); if(objectModel) $("#edit-marker-object-heading").val(data.heading); } else { $("#edit-marker-coord-x").val(data.x) $("#edit-marker-coord-y").val(data.y) $("#edit-marker-coord-z").val(data.z) } }) $("#delete-marker-btn").click(async function(){ let editMarkerModal = $("#edit-marker-dialog-modal"); let markerId = editMarkerModal.data("markerId"); editMarkerModal.modal("hide"); if(!markerId) return; if(! await confirmDeletion(getLocalizedText("menu:do_you_want_to_delete_this_marker"))) return; const data = await $.post(`https://${resName}/delete-marker`, JSON.stringify({ markerId: markerId })) if (!data.isSuccessful) { showError(data.message); return } if( $("#edit-marker-form").data("isPublic") ) { fillPublicMarkers(); } else { fillJobMarkers(); } }) async function getOpenExternalClothingMenu() { return await $.post(`https://${resName}/getOpenExternalClothingMenu`); } async function getInventoryScriptUsed() { return await $.post(`https://${resName}/getInventoryScriptUsed`); } async function setCurrentMarkerData(markerType, markerData) { // Resets animations from old opened marker $("#edit-marker-dialog-modal").data("animations", []); markerData = markerData || {}; switch(markerType) { case "garage": { let spawnpointsDiv = $("#temporary-garage-spawnpoints-list"); spawnpointsDiv.empty(); if (markerData.spawnPoints) { markerData.spawnPoints.forEach(spawnPointData => { addGarageSpawnpoint(spawnpointsDiv, spawnPointData); }) } $("#garage-data-model-tbody").empty(); if (markerData.vehicles) { for (const [vehicleModel, vehicleData] of Object.entries(markerData.vehicles)) { addVehicleToTemporaryGarage(vehicleModel, vehicleData) } } break; } case "garage_buyable": { let spawnpointsDiv = $("#buyable-garage-spawnpoints-list"); spawnpointsDiv.empty(); if (markerData.spawnPoints) { markerData.spawnPoints.forEach(spawnPointData => { addGarageSpawnpoint(spawnpointsDiv, spawnPointData); }) } $("#garage-buyable-vehicles").empty(); if(markerData.vehicles) { for (const [vehicleName, price] of Object.entries(markerData.vehicles)) { var vehicleInputGroup = $(`
    `) var vehicleInput = $(``); var moneySpan = $(`$`) var vehiclePrice = $(``); var deleteVehicle = $(``); vehicleInputGroup.append(vehicleInput, moneySpan, vehiclePrice, deleteVehicle); $(deleteVehicle).click(function () { $(this).parent().remove(); }) $("#garage-buyable-vehicles").append(vehicleInputGroup) } } $("#garage-buyable-vehicle-model").val(""); $("#garage-buyable-vehicle-price").val(""); break; } case "garage_owned": { let spawnpointsDiv = $("#owned-garage-spawnpoints-list"); spawnpointsDiv.empty(); if (markerData.spawnPoints) { markerData.spawnPoints.forEach(spawnPointData => { addGarageSpawnpoint(spawnpointsDiv, spawnPointData); }) } break; } case "boss": { let canWashMoney = markerData.canWashMoney; let canWithdraw = markerData.canWithdraw; let canDeposit = markerData.canDeposit; let canEmployees = markerData.canEmployees; let canGrades = markerData.canGrades; toggleBossWashMoneyOptions(canWashMoney); if(canWashMoney) { $("#boss-data-washmoney-percentage").val(markerData.washMoneyReturnPercentage); $("#boss-data-washmoney-to-society-account").prop("checked", markerData.washMoneyGoesToSocietyAccount); } $("#boss-data-washmoney").prop('checked', canWashMoney); $("#boss-data-withdraw").prop('checked', canWithdraw); $("#boss-data-deposit").prop('checked', canDeposit); $("#boss-data-employees").prop('checked', canEmployees); $("#boss-data-grades").prop('checked', canGrades); $("#boss-data-max-salary").val(markerData.maxSalary); break; } case "shop": { setChoosenObject( $("#shop-new-item-name-div"), null ); $("#shop-data-item-price").val("") $('#shop-data-items-container').empty(); if (markerData.itemsOnSale) { markerData.itemsOnSale.forEach(itemData => { addItemToShop(itemData.object, itemData) }) } break; } case "market": { $("#market-modal-items-tbody").empty(); markerData?.items?.forEach(item => { addItemToMarket(item.object, item.minPrice, item.maxPrice, item.blackMoney, item.sellTime); }) $("#market-modal-society-percentage").val(markerData.percentageForSociety); break; } case "crafting_table": { let craftablesDiv = $("#craftables"); craftablesDiv.empty(); if(markerData.craftablesItems) { markerData.craftablesItems.forEach(craftableItem => { addNewCraftableToCraftables(craftableItem.resultObject, craftableItem) }) } break; } case "armory": { $("#armory-is-shared").prop("checked", markerData.isShared); $("#armory-refill-on-take").prop("checked", markerData.refillOnTake); break; } case "job_outfit": { $("#job-outfit-outfits").empty(); if(!markerData.outfits) return; const openExternalClothingMenu = await getOpenExternalClothingMenu(); if(openExternalClothingMenu) { hideAllMarkerSettings(); $("#specific-marker-settings").hide(); swal(getLocalizedText("menu:note"), getLocalizedText("menu:job_outfit_warning"), "info"); return; } markerData.outfits.forEach(outfit => { createNewOutfit(outfit) }) break; } case "teleport": { if(markerData.teleportCoords) { $("#teleport-x").val(markerData.teleportCoords.x); $("#teleport-y").val(markerData.teleportCoords.y); $("#teleport-z").val(markerData.teleportCoords.z); } break; } case "harvest": { $("#harvest-modal-items").empty(); if(markerData.harvestableItems) { markerData.harvestableItems.forEach(item => { addItemToHarvestable(item.object, item.minQuantity, item.maxQuantity, item.time, item.chances); }); } if(markerData.animations) { $("#edit-marker-dialog-modal").data("animations", markerData.animations) } $("#harvest-item-requires-tool").prop("checked", markerData.itemTool != undefined).change(); setChoosenObject( $("#harvest-item-tool-div"), markerData.itemTool ) $("#harvest-item-tool-lose-on-use").prop("checked", markerData.itemToolLoseQuantity).change(); $("#harvest-item-tool-lose-quantity").val(markerData.itemToolLoseQuantity); $("#harvest-item-tool-lose-probability").val(markerData.itemToolLoseProbability); toggleDisappearsAfterUse(markerData.disappearAfterUse); $("#harvest-disappear-seconds").val(markerData.disappearSeconds); $("#harvest-requires-minimum-account-money").prop("checked", markerData.requiresMinimumAccountMoney || false).change(); $("#harvest-minimum-account-name").val(markerData.minimumAccountName); $("#harvest-minimum-account-amount").val(markerData.minimumAccountAmount); break; } case "process": { setChoosenObject( $("#process-modal-remove-item-div"), markerData.itemToRemove); $("#item-to-remove-quantity").val(markerData?.itemToRemoveQuantity || 1); setChoosenObject( $("#process-modal-give-item-div"), markerData.itemToAdd); $("#item-to-add-quantity").val(markerData?.itemToAddQuantity || 1); $("#process-time").val(markerData?.timeToProcess || 5); $("#edit-marker-dialog-modal").data("animations", markerData?.animations) $("#process-requires-minimum-account-money").prop("checked", markerData.requiresMinimumAccountMoney || false).change(); $("#process-minimum-account-name").val(markerData.minimumAccountName); $("#process-minimum-account-amount").val(markerData.minimumAccountAmount); break; } case "weapon_upgrader": { if(markerData.componentsPrices) { // set empty all, so disabled components will remain disabled $("#weapon-upgrader-components").find(".form-control").each(function() { $(this).val(""); }) for(const [componentName, componentPrice] of Object.entries(markerData.componentsPrices)) { $("#weapon-upgrader-components").find(`[data-componentname=${componentName}]`).val(componentPrice); } } if(markerData.tintsPrices) { // set empty all, so disabled tints will remain disabled $("#weapon-upgrader-tints").find(".form-control").each(function() { $(this).val(""); }) for(const [tintId, tintPrice] of Object.entries(markerData.tintsPrices)) { $("#weapon-upgrader-tints").find(`[data-tintid=${tintId}]`).val(tintPrice); } } break; } case "job_shop": { let allJobsSelect = $("#job-shop-all-jobs"); allJobsSelect.find(".job-shop-job").remove(); const jobs = await $.post(`https://${resName}/getJobsData`); let jobsRanks = {} for(const [_, jobData] of Object.entries(jobs)) { if(jobData.name) { let jobDiv = $(``); jobsRanks[jobData.name] = jobData.ranks allJobsSelect.append(jobDiv); } } allJobsSelect.data("ranks", jobsRanks); $("#job-shop-all-jobs").val(markerData.allowedJob).change(); $("#job-shop-all-ranks").val(markerData.minimumRank); break; } } } function getCurrentMarkerData(markerType) { let markerData = {}; switch(markerType) { case "garage": { let vehicles = {}; let vehiclesObject = $("#garage-data-model-tbody").children(".vehicle"); vehiclesObject.each(function (index, element) { let vehicleModel = $(element).find(".vehicle-model").text(); let vehiclePrimaryColor = $(element).find(".vehicle-primary-color").val(); let vehicleSecondaryColor = $(element).find(".vehicle-secondary-color").val(); let vehicleLivery = parseInt( $(element).find(".vehicle-livery").val() ); let vehiclePlate = $(element).find(".vehicle-custom-plate").val(); vehicles[vehicleModel] = { primaryColor: vehiclePrimaryColor, secondaryColor: vehicleSecondaryColor, livery: vehicleLivery || null, plate: vehiclePlate || null } }) markerData = { vehicles: vehicles, spawnPoints: getGarageSpawnpoints( $("#temporary-garage-spawnpoints-list") ), } break; } case "garage_buyable": { let vehicles = {}; let vehiclesObject = $("#garage-buyable-vehicles").find(".vehicle"); vehiclesObject.each(function (index, element) { let model = $(element).find(".vehicle-model").val(); let price = parseInt( $(element).find(".vehicle-price").val() ); vehicles[model] = price; }); markerData = { spawnPoints: getGarageSpawnpoints( $("#buyable-garage-spawnpoints-list") ), vehicles: vehicles } break; } case "garage_owned": { markerData = { spawnPoints: getGarageSpawnpoints( $("#owned-garage-spawnpoints-list") ), } break; } case "boss": { let canWashMoney = $("#boss-data-washmoney").prop('checked') let canWithdraw = $("#boss-data-withdraw").prop('checked') let canDeposit = $("#boss-data-deposit").prop('checked') let canEmployees = $("#boss-data-employees").prop('checked') let canGrades = $("#boss-data-grades").prop('checked') if(canWashMoney) { var washMoneyReturnPercentage = parseInt($("#boss-data-washmoney-percentage").val()); var washMoneyGoesToSocietyAccount = $("#boss-data-washmoney-to-society-account").prop("checked"); } markerData = { canWashMoney: canWashMoney, washMoneyReturnPercentage: washMoneyReturnPercentage, washMoneyGoesToSocietyAccount: washMoneyGoesToSocietyAccount, canWithdraw: canWithdraw, canDeposit: canDeposit, canEmployees: canEmployees, canGrades: canGrades, maxSalary: parseInt( $("#boss-data-max-salary").val() ), } break; } case "shop": { let itemsOnSale = []; let itemsContainer = $("#shop-data-items-container") itemsContainer.children().each(function (index, element) { let object = $(element).data("object"); let itemPrice = $(element).data("item-price"); let blackMoney = $(element).find(".item-blackmoney").prop("checked"); if (!object || itemPrice === undefined) return; itemsOnSale.push({ object, price: itemPrice, blackMoney }) }) markerData = { itemsOnSale: itemsOnSale } break; } case "market": { let items = []; let marketBodyDiv = $("#market-modal-items-tbody") let itemsDivs = marketBodyDiv.children(".item") itemsDivs.each(function(index, element) { let itemDiv = $(element) let object = itemDiv.data("object"); let itemMinPrice = parseInt(itemDiv.find(".item-min-price").text()); let itemMaxPrice = parseInt(itemDiv.find(".item-max-price").text()); let blackMoney = itemDiv.find(".item-blackmoney").prop("checked") let sellTime = parseInt(itemDiv.find(".item-selltime").val()); items.push({ object, minPrice: itemMinPrice, maxPrice: itemMaxPrice, blackMoney: blackMoney, sellTime: sellTime }); }); markerData = { items: items, percentageForSociety: parseInt( $("#market-modal-society-percentage").val() ) } break; } case "crafting_table": { let craftablesItems = []; $("#craftables").children().each(function(craftableIndex, craftableElement) { let craftable = $(craftableElement); let resultObject = getChoosenObject( craftable.find('.craftable-object-div') ); let resultItemQuantity = parseInt( craftable.find('.result-item-quantity').val() ); let resultItemCraftingTime = parseInt( craftable.find('.result-item-crafting-time').val() ); let recipes = []; craftable.find('.craft-ingredients').children().each(function(ingredientIndex, ingredientElement){ var ingredientDiv = $(ingredientElement) var ingredientObject = ingredientDiv.data("object"); var ingredientQuantity = ingredientDiv.data("item-quantity"); var loseOnUse = ingredientDiv.find(".lose-on-use-checkbox").prop("checked") recipes.push({ object: ingredientObject, quantity: ingredientQuantity, loseOnUse }); }) craftablesItems.push({ resultObject, recipes, animations: craftable.data("animations"), quantity: resultItemQuantity || 1, craftingTime: resultItemCraftingTime || 8 }); }) markerData = { craftablesItems } break; } case "armory": { markerData = { isShared: $("#armory-is-shared").prop("checked"), refillOnTake: $("#armory-refill-on-take").prop("checked") } break; } case "job_outfit": { let jobOutfitsDiv = $("#job-outfit-outfits"); let outfitsDiv = jobOutfitsDiv.children(); let outfits = []; outfitsDiv.each(function(index, outfitDivRaw){ let outfitDiv = $(outfitDivRaw); let outfit = getOutfitFromOutfitDiv(outfitDiv); outfits.push(outfit); }) markerData = { outfits: outfits } break; } case "teleport": { markerData = { teleportCoords: { x: parseFloat( $(`#teleport-x`).val() ), y: parseFloat( $(`#teleport-y`).val() ), z: parseFloat( $(`#teleport-z`).val() ), } } break; } case "harvest": { let harvestableItems = []; $("#harvest-modal-items").find(".harvestable-item").each(function(index, element) { let harvestableItem = { object: getChoosenObject( $(this).find(".harvest-object-div") ), minQuantity: parseInt( $(this).find(".harvest-item-min-quantity").val() ), maxQuantity: parseInt( $(this).find(".harvest-item-max-quantity").val() ), time: parseInt( $(this).find(".harvest-item-time").val() ), chances: parseInt( $(this).find(".harvest-item-chance").val()), }; harvestableItems.push(harvestableItem); }) if($("#harvest-item-requires-tool").prop("checked")) { var itemTool = getChoosenObject( $("#harvest-item-tool-div") ); } if($("#harvest-item-tool-lose-on-use").prop("checked")) { var itemToolLoseQuantity = parseInt($("#harvest-item-tool-lose-quantity").val()); var itemToolLoseProbability = parseInt( $("#harvest-item-tool-lose-probability").val() ); } markerData = { harvestableItems, animations: $("#edit-marker-dialog-modal").data("animations"), itemTool, itemToolLoseQuantity, itemToolLoseProbability, disappearAfterUse: $("#harvest-disappear-after-use").prop("checked"), disappearSeconds: parseInt( $("#harvest-disappear-seconds").val() ), requiresMinimumAccountMoney: $("#harvest-requires-minimum-account-money").prop("checked"), minimumAccountName: $("#harvest-minimum-account-name").val(), minimumAccountAmount: parseInt( $("#harvest-minimum-account-amount").val() ), } break; } case "process": { markerData = { itemToRemove: getChoosenObject( $("#process-modal-remove-item-div") ), itemToRemoveQuantity: parseInt($("#item-to-remove-quantity").val()), itemToAdd: getChoosenObject( $("#process-modal-give-item-div") ), itemToAddQuantity: parseInt($("#item-to-add-quantity").val()), timeToProcess: parseInt($("#process-time").val()), animations: $("#edit-marker-dialog-modal").data("animations"), requiresMinimumAccountMoney: $("#process-requires-minimum-account-money").prop("checked"), minimumAccountName: $("#process-minimum-account-name").val(), minimumAccountAmount: parseInt( $("#process-minimum-account-amount").val() ) } break; } case "weapon_upgrader": { let weaponsComponentsDiv = $("#weapon-upgrader-components"); let weaponsTintsDiv = $("#weapon-upgrader-tints"); let componentsPrices = {}; let tintsPrices = {}; weaponsComponentsDiv.find(".form-control").each(function(index, element) { let componentDiv = $(element) let componentName = componentDiv.data("componentname") let componentPrice = componentDiv.val() if(componentPrice) { componentsPrices[componentName] = componentPrice } }) weaponsTintsDiv.find(".form-control").each(function(index, element) { let tintDiv = $(element) let tintId = parseInt(tintDiv.data("tintid")) let tintPrice = parseInt(tintDiv.val()) if(tintPrice) { tintsPrices[tintId] = tintPrice } }) markerData = { componentsPrices: componentsPrices, tintsPrices: tintsPrices } break; } case "job_shop": { let jobName = $("#job-shop-all-jobs").val(); if(!jobName) return; let rankGrade = parseInt($("#job-shop-all-ranks").val()); if(jobName && !isNaN(rankGrade)) { markerData = { allowedJob: jobName, minimumRank: rankGrade } } break; } } return markerData; } $("#edit-marker-form").submit(function(event){ if (!this.checkValidity()) { event.stopPropagation(); event.preventDefault(); return; } let editMarkerModal = $("#edit-marker-dialog-modal"); let markerId = editMarkerModal.data("markerId"); let isPublicMarker = $("#edit-marker-form").data("isPublic"); let enableMarkerBlip = $("#edit-marker-map-blip").prop("checked"); if(enableMarkerBlip) { var blipSpriteId = parseInt( $("#edit-marker-sprite-id").val() ); var blipColor = parseInt( $("#edit-marker-blip-color").val() ); var blipScale = parseFloat( $("#edit-marker-blip-scale").val() ); } let color = hexToRgb( $("#edit-marker-color").val() ); let enableNPC = $("#edit-marker-npc").prop("checked"); if(enableNPC) { var npcModel = $("#edit-marker-npc-model").val(); var npcHeading = parseFloat( $("#edit-marker-npc-heading").val() ); } let enableObject = $("#edit-marker-object").prop("checked"); if(enableObject) { var objectModel = $("#edit-marker-object-model").val(); } let gradesType = $("input[type=radio][name=markerGradeType]:checked").val(); if(gradesType === "minimumGrade") { var minGrade = parseInt( $("#edit-marker-min-grade").val() ); } else if(gradesType === "specificGrades") { var specificGrades = $("#edit-marker-specific-grades").data("grades") || {}; } let data = { markerId: markerId, label: $("#edit-marker-label").val(), gradesType: gradesType, minGrade: minGrade, specificGrades: specificGrades, coords: { x: parseFloat( $("#edit-marker-coord-x").val() ), y: parseFloat( $("#edit-marker-coord-y").val() ), z: parseFloat( $("#edit-marker-coord-z").val() ), }, blip: { spriteId: blipSpriteId, color: blipColor, scale: blipScale, }, markerType: parseInt( $("#edit-marker-type").val() ), scale: { x: parseFloat( $("#edit-marker-scale-x").val() ), y: parseFloat( $("#edit-marker-scale-y").val() ), z: parseFloat( $("#edit-marker-scale-z").val() ) }, color: { r: color.r, g: color.g, b: color.b, alpha: parseInt( $("#edit-marker-alpha").val() ) }, ped: { model: npcModel, heading: npcHeading }, object: { model: objectModel, heading: parseFloat( $("#edit-marker-object-heading").val() ) } } let markerData = getCurrentMarkerData(allMarkers[markerId].type); $.post(`https://${resName}/update-marker`, JSON.stringify(data), function (data) { if (data.isSuccessful) { let markerType = allMarkers[markerId].type if(MARKERS_INFOS[markerType].requiresDataUpdate) { $.post(`https://${resName}/update-marker-data`, JSON.stringify({ markerId: markerId, markerData: markerData }), function (data) { if (data.isSuccessful) { editMarkerModal.modal("hide"); } else { showError(data.message) } if(isPublicMarker) { fillPublicMarkers(); } else { fillJobMarkers(); } }); } else { editMarkerModal.modal("hide"); if(isPublicMarker) { fillPublicMarkers(); } else { fillJobMarkers(); } } } else { showError(data.message) } }) }) function gradesDialog(enabledGrades) { return new Promise(resolve => { let gradesModal = $("#input-grades-dialog-modal") let gradesList = $("#grades-list"); gradesList.empty(); let jobName = $("#edit-job").data("jobName"); $.post(`https://${resName}/getJobGrades`, JSON.stringify({jobName: jobName}), function(jobGrades) { for( const[_, gradeData] of Object.entries(jobGrades) ) { let gradeDiv = $(`
    `); gradesList.append(gradeDiv); } gradesModal.modal("show"); }) let confirmButton = $("#input-grades-dialog-confirm"); confirmButton.unbind("click"); confirmButton.click(function() { let grades = {}; $(".grade:checked").each(function() { grades[ parseInt($(this).val()) ] = true; }) gradesModal.modal("hide"); resolve(grades); }) }); } function setSpecificGrades(grades) { let specificGradesDiv = $("#edit-marker-specific-grades"); specificGradesDiv.data("grades", grades); specificGradesDiv.val( Object.keys(grades).join(",")); } $("#edit-marker-specific-grades-choose-btn").click(async function() { let enabledGrades = $("#edit-marker-specific-grades").data("grades") || {}; let grades = await gradesDialog(enabledGrades); setSpecificGrades(grades); }) $("#marker-data-add-vehicle").click(function () { var modelDiv = $("#marker-data-vehicle-model"); var model = modelDiv.val(); // Clears input modelDiv.val(""); if (model) { modelDiv.removeClass("is-invalid"); addVehicleToTemporaryGarage(model) } else { modelDiv.addClass("is-invalid"); } }) function getGarageSpawnpoints(listDiv) { let spawnpoints = []; listDiv.find(".spawnpoint-div").each(function() { let spawnpointData = { coords: { x: parseFloat( $(this).find(".spawnpoint-coords-x").val() ), y: parseFloat( $(this).find(".spawnpoint-coords-y").val() ), z: parseFloat( $(this).find(".spawnpoint-coords-z").val() ), }, heading: parseFloat( $(this).find(".spawnpoint-heading").val() ), radius: parseInt( $(this).find(".spawnpoint-radius").val() ) } spawnpoints.push(spawnpointData); }) return spawnpoints; } function addGarageSpawnpoint(listDiv, spawnpointData) { let div = $(`
    Coords Heading Radius
    `); div.find(".delete-spawnpoint-btn").click(function() { div.remove(); }); div.find(".current-coords-btn").click(async function() { const data = await getCurrentCoordsAndHeading(); div.find(".spawnpoint-coords-x").val(data.coords.x); div.find(".spawnpoint-coords-y").val(data.coords.y); div.find(".spawnpoint-coords-z").val(data.coords.z); div.find(".spawnpoint-heading").val(data.heading); }); if(spawnpointData) { div.find(".spawnpoint-coords-x").val(spawnpointData.coords.x); div.find(".spawnpoint-coords-y").val(spawnpointData.coords.y); div.find(".spawnpoint-coords-z").val(spawnpointData.coords.z); div.find(".spawnpoint-heading").val(spawnpointData.heading); div.find(".spawnpoint-radius").val(spawnpointData.radius); } listDiv.append(div); } $("#temporary-garage-add-spawnpoint").click(function() { addGarageSpawnpoint( $("#temporary-garage-spawnpoints-list") ); }) $("#buyable-garage-add-spawnpoint").click(function() { addGarageSpawnpoint( $("#buyable-garage-spawnpoints-list") ); }) $("#owned-garage-add-spawnpoint").click(function() { addGarageSpawnpoint( $("#owned-garage-spawnpoints-list") ); }) function addItemToShop(object, itemData) { var newItem = $(`

    ${object.name}

    $${itemData.price}

    `) newItem.data("item-price", parseInt(itemData.price)); newItem.find(".item-blackmoney").prop("checked", itemData.blackMoney); newItem.find(".btn").click(function () { newItem.remove(); }) newItem.data("object", object); $('#shop-data-items-container').append(newItem) } $("#shop-data-add-btn").click(function () { var isEverythingValid = true let choosenObject = getChoosenObject( $("#shop-new-item-name-div") ); var itemPriceDiv = $("#shop-data-item-price") var itemName = choosenObject.name; var itemPrice = itemPriceDiv.val(); let itemData = { price: itemPrice } if (!itemName) return; if (!itemPrice) { itemPriceDiv.addClass("is-invalid") isEverythingValid = false } else { itemPriceDiv.removeClass("is-invalid") } if (!isEverythingValid) return; addItemToShop(choosenObject, itemData); }) $("#garage-buyable-add-vehicle").click(function () { var isEverythingValid = true; var modelDiv = $("#garage-buyable-vehicle-model"); var model = modelDiv.val(); var priceDiv = $("#garage-buyable-vehicle-price"); var price = parseInt(priceDiv.val()); // Clears input modelDiv.val(""); priceDiv.val(""); if (model) { modelDiv.removeClass("is-invalid"); } else { modelDiv.addClass("is-invalid"); isEverythingValid = false } if(price) { priceDiv.removeClass("is-invalid") } else { priceDiv.addClass("is-invalid") isEverythingValid = false } if(isEverythingValid) { var vehicleInputGroup = $(`
    `) var vehicleInput = $(``); var moneySpan = $(`$`) var vehiclePrice = $(``); var deleteVehicle = $(``); vehicleInputGroup.append(vehicleInput, moneySpan, vehiclePrice, deleteVehicle); $(deleteVehicle).click(function () { $(this).parent().remove(); }) $("#garage-buyable-vehicles").append(vehicleInputGroup) } }) $("#garage-buyable-current-coords").click(function() { $.post(`https://${resName}/get-current-coords`, {}, function (data) { var coords = data.coords; var heading = data.heading; if (coords) { $("#garage-buyable-spawnpoint-x").val(coords.x) $("#garage-buyable-spawnpoint-y").val(coords.y) $("#garage-buyable-spawnpoint-z").val(coords.z) } if (heading) { $("#garage-buyable-heading").val(heading) } }) }) function addNewCraftableToCraftables(object, craftingData) { var craftablesDiv = $("#craftables"); var newCraftable = $(`
    ${getLocalizedText("menu:dynamic:marker:crafting_table:quantity")} ${getLocalizedText("menu:dynamic:marker:crafting_table:time_to_craft")}
    ${getLocalizedText("menu:dynamic:marker:crafting_table:item_id")} ${getLocalizedText("menu:dynamic:marker:crafting_table:item_quantity")} ${getLocalizedText("menu:dynamic:marker:crafting_table:lose_on_use")} ${getLocalizedText("menu:dynamic:marker:crafting_table:remove")}
    ${getLocalizedText("menu:dynamic:marker:crafting_table:item_quantity")}

    `) loadChooseObjectDivs( newCraftable.find(".craftable-object-div"), object) loadChooseObjectDivs( newCraftable.find(".ingredient-object-div")) newCraftable.find(".remove-craft-btn").click(function() { newCraftable.remove(); }) newCraftable.find(".animations-craft-btn").click(function() { inputAnimations(newCraftable.data("animations"), function(animations) { newCraftable.data("animations", animations) }); }) var addToCraftBtn = newCraftable.find(".add-to-craft-btn") addToCraftBtn.click(function() { var itemQuantityDiv = newCraftable.find(".crafting-table-item-quantity"); const object = getChoosenObject( newCraftable.find(".ingredient-object-div") ); var itemQuantity = parseInt( itemQuantityDiv.val() ); if(!object) return; if(!itemQuantity || itemQuantity <= 0) { itemQuantityDiv.addClass("is-invalid"); return; } else { itemQuantityDiv.removeClass("is-invalid"); } var craftIngredientsDiv = newCraftable.find(".craft-ingredients"); let newCraftItem = $(` ${object.name} ${itemQuantity}
    `) newCraftItem.data("object", object); newCraftItem.find('.remove-ingredient-btn').click(function() { newCraftItem.remove() }) craftIngredientsDiv.append(newCraftItem) setChoosenObject( newCraftable.find(".ingredient-object-div"), null ) itemQuantityDiv.val(""); }) if(craftingData?.recipes) { let craftIngredientsDiv = newCraftable.find('.craft-ingredients'); craftingData.recipes.forEach(ingredientData => { let newCraftItem = $(` ${ingredientData.object.name} ${ingredientData.quantity}
    `) newCraftItem.data("object", ingredientData.object); let loseOnUse = ingredientData.loseOnUse newCraftItem.find(".lose-on-use-checkbox").prop("checked", loseOnUse) newCraftItem.find('.remove-ingredient-btn').click(function() { newCraftItem.remove() }) craftIngredientsDiv.append(newCraftItem); }) } newCraftable.data("animations", craftingData?.animations || undefined) craftablesDiv.append(newCraftable); } $("#crafting-table-new-craft-btn").click(function() { addNewCraftableToCraftables() }) $("#delete-armory-content").click(async function(){ let armoryModal = $("#armory-data-modal"); let markerId = armoryModal.data("markerId") armoryModal.modal("hide"); if(! await confirmDeletion(getLocalizedText("menu:do_you_want_to_delete_armory_content"))) return; const data = $.post(`https://${resName}/delete-armory-inventory`, JSON.stringify({ markerId: markerId })); if(!data.isSuccessful) { showError(data.message) } }) $("#delete-stash-inventory").click(async function() { let editMarkerModal = $("#edit-marker-dialog-modal"); let markerId = editMarkerModal.data("markerId"); if(! await confirmDeletion(getLocalizedText("menu:do_you_want_to_delete_stash_content"))) return; const data = await $.post(`https://${resName}/delete-stash-inventory`, JSON.stringify({ markerId: markerId })); if(!data.isSuccessful) { showError(data.message) } }) function createNewOutfit(outfit){ outfit = outfit || {}; outfit.tshirt_1 = outfit.tshirt_1 || 0; outfit.tshirt_2 = outfit.tshirt_2 || 0; outfit.torso_1 = outfit.torso_1 || 0; outfit.torso_2 = outfit.torso_2 || 0; outfit.decals_1 = outfit.decals_1 || 0; outfit.decals_2 = outfit.decals_2 || 0; outfit.arms = outfit.arms || 0; outfit.arms_2 = outfit.arms_2 || 0; outfit.pants_1 = outfit.pants_1 || 0; outfit.pants_2 = outfit.pants_2 || 0; outfit.shoes_1 = outfit.shoes_1 || 0; outfit.shoes_2 = outfit.shoes_2 || 0; outfit.mask_1 = outfit.mask_1 || 0; outfit.mask_2 = outfit.mask_2 || 0; outfit.bproof_1 = outfit.bproof_1 || 0; outfit.bproof_2 = outfit.bproof_2 || 0; outfit.chain_1 = outfit.chain_1 || 0; outfit.chain_2 = outfit.chain_2 || 0; outfit.helmet_1 = outfit.helmet_1 || -1; outfit.helmet_2 = outfit.helmet_2 || 0; outfit.glasses_1 = outfit.glasses_1 || 0; outfit.glasses_2 = outfit.glasses_2 || 0; outfit.bags_1 = outfit.bags_1 || 0; outfit.bags_2 = outfit.bags_2 || 0; let outfitsDiv = $("#job-outfit-outfits") let outfitId = $("#job-outfit-outfits").children().length + 1; let outfitDiv = $(`

    T-Shirt Color
    Torso Color
    Decals Color
    Arms Color
    Pants Color
    Shoes Color
    Mask Color
    Bulletproof Color
    Chain Color
    Helmet/Hat Color
    Glasses Color
    Bag Color
    `) outfitDiv.find(".current-outfit-btn").click(function(){ $.post(`https://${resName}/get-current-outfit`, JSON.stringify({}), function (data) { outfitDiv.find(".outfit-tshirt").val(data.tshirt_1) outfitDiv.find(".outfit-tshirt-color").val(data.tshirt_2) outfitDiv.find(".outfit-torso").val(data.torso_1) outfitDiv.find(".outfit-torso-color").val(data.torso_2) outfitDiv.find(".outfit-decals").val(data.decals_1) outfitDiv.find(".outfit-decals-color").val(data.decals_2) outfitDiv.find(".outfit-arms").val(data.arms) outfitDiv.find(".outfit-arms-color").val(data.arms_2) outfitDiv.find(".outfit-pants").val(data.pants_1) outfitDiv.find(".outfit-pants-color").val(data.pants_2) outfitDiv.find(".outfit-shoes").val(data.shoes_1) outfitDiv.find(".outfit-shoes-color").val(data.shoes_2) outfitDiv.find(".outfit-mask").val(data.mask_1) outfitDiv.find(".outfit-mask-color").val(data.mask_2) outfitDiv.find(".outfit-bulletproof").val(data.bproof_1) outfitDiv.find(".outfit-bulletproof-color").val(data.bproof_2) outfitDiv.find(".outfit-chain").val(data.chain_1) outfitDiv.find(".outfit-chain-color").val(data.chain_2) outfitDiv.find(".outfit-helmet").val(data.helmet_1) outfitDiv.find(".outfit-helmet-color").val(data.helmet_2) outfitDiv.find(".outfit-glasses").val(data.glasses_1) outfitDiv.find(".outfit-glasses-color").val(data.glasses_2) outfitDiv.find(".outfit-bag").val(data.bags_1) outfitDiv.find(".outfit-bag-color").val(data.bags_2) }); }) outfitDiv.find(".delete-outfit-btn").click(async function(){ if(! await confirmDeletion(getLocalizedText("menu:do_you_want_to_delete_outfit"))) return; outfitDiv.remove(); }) $(outfitsDiv).append(outfitDiv) } function getOutfitFromOutfitDiv(outfitDiv) { let outfit = {} outfit.label = outfitDiv.data("label") outfit.tshirt_1 = parseInt(outfitDiv.find(".outfit-tshirt").val()) || 0; outfit.tshirt_2 = parseInt(outfitDiv.find(".outfit-tshirt-color").val()) || 0; outfit.torso_1 = parseInt(outfitDiv.find(".outfit-torso").val()) || 0; outfit.torso_2 = parseInt(outfitDiv.find(".outfit-torso-color").val()) || 0; outfit.decals_1 = parseInt(outfitDiv.find(".outfit-decals").val()) || 0; outfit.decals_2 = parseInt(outfitDiv.find(".outfit-decals-color").val()) || 0; outfit.arms = parseInt(outfitDiv.find(".outfit-arms").val()) || 0; outfit.arms_2 = parseInt(outfitDiv.find(".outfit-arms-color").val()) || 0; outfit.pants_1 = parseInt(outfitDiv.find(".outfit-pants").val()) || 0; outfit.pants_2 = parseInt(outfitDiv.find(".outfit-pants-color").val()) || 0; outfit.shoes_1 = parseInt(outfitDiv.find(".outfit-shoes").val()) || 0; outfit.shoes_2 = parseInt(outfitDiv.find(".outfit-shoes-color").val()) || 0; outfit.mask_1 = parseInt(outfitDiv.find(".outfit-mask").val()) || 0; outfit.mask_2 = parseInt(outfitDiv.find(".outfit-mask-color").val()) || 0; outfit.bproof_1 = parseInt(outfitDiv.find(".outfit-bulletproof").val()) || 0; outfit.bproof_2 = parseInt(outfitDiv.find(".outfit-bulletproof-color").val()) || 0; outfit.chain_1 = parseInt(outfitDiv.find(".outfit-chain").val()) || 0; outfit.chain_2 = parseInt(outfitDiv.find(".outfit-chain-color").val()) || 0; outfit.helmet_1 = parseInt(outfitDiv.find(".outfit-helmet").val()) || -1; outfit.helmet_2 = parseInt(outfitDiv.find(".outfit-helmet-color").val()) || 0 outfit.glasses_1 = parseInt(outfitDiv.find(".outfit-glasses").val()) || 0; outfit.glasses_2 = parseInt(outfitDiv.find(".outfit-glasses-color").val()) || 0; outfit.bags_1 = parseInt(outfitDiv.find(".outfit-bag").val()) || 0; outfit.bags_2 = parseInt(outfitDiv.find(".outfit-bag-color").val()) || 0; return outfit; } $("#job-outfit-new-outfit-btn").click(function(){ inputDialog("Create new outfit", [ { id: "outfitLabel", label: "New outfit label:" }, ], function (data) { let outfit = {label: data.outfitLabel} createNewOutfit(outfit); }); }) $("#teleport-current-coords-btn").click(function(){ $.post(`https://${resName}/get-current-coords`, {}, function (data) { var coords = data.coords; if (coords) { $(`#teleport-x`).val(coords.x) $(`#teleport-y`).val(coords.y) $(`#teleport-z`).val(coords.z) } }) }); function addItemToMarket(object, itemMinPrice, itemMaxPrice, blackMoney = false, sellTime = 0) { let itemsTableDiv = $("#market-modal-items-tbody"); let itemDiv = $(` ${object.name} ${itemMinPrice} ${itemMaxPrice} `) let deleteBtn = $(``); deleteBtn.click(function(){ itemDiv.remove(); }) itemDiv.find(".delete-btn").append(deleteBtn); itemDiv.find(".item-blackmoney").prop("checked", blackMoney); itemDiv.data("object", object); itemsTableDiv.append(itemDiv); } $("#market-modal-new-item-btn").click(function(){ let itemIdDiv = $("#market-modal-new-item-name-input"); const chooseObjectDiv = $("#market-new-item-name-div"); let object = getChoosenObject(chooseObjectDiv); let itemMinPriceDiv = $("#market-modal-new-item-min-price-input"); let itemMaxPriceDiv = $("#market-modal-new-item-max-price-input"); let itemMinPrice = itemMinPriceDiv.val(); let itemMaxPrice = itemMaxPriceDiv.val(); if(object) { itemIdDiv.removeClass("is-invalid"); } else { itemIdDiv.addClass("is-invalid"); } if(itemMinPrice) { itemMinPriceDiv.removeClass("is-invalid"); } else { itemMinPriceDiv.addClass("is-invalid"); } if(itemMaxPrice) { itemMaxPriceDiv.removeClass("is-invalid"); } else { itemMaxPriceDiv.addClass("is-invalid"); } if(object && itemMinPrice && itemMaxPrice) { setChoosenObject(chooseObjectDiv, null); itemMinPriceDiv.val(""); itemMaxPriceDiv.val(""); addItemToMarket(object, itemMinPrice, itemMaxPrice); } }) function inputAnimations(animations, cb) { let animationsModal = $("#animations-modal"); let animationsForm = $("#animations-modal-form"); $("#animations").empty(); if(animations && animations.length > 0) { animations.forEach(animation => { addAnimation(animation) }) } else { addAnimation(); } animationsForm.unbind(); animationsForm.submit(function(event) { if (!this.checkValidity()) { event.stopPropagation(); event.preventDefault(); return; } else { $(animationsForm).removeClass("was-validated"); } let animations = []; $("#animations").find(".animation-container").each(function() { let currentAnimDiv = $(this); let animType = currentAnimDiv.find(".animation-type").prop("checked"); // If it's a scenario if(animType) { animations.push({ type: "scenario", scenarioName: currentAnimDiv.find(".scenario-name").val(), scenarioDuration: parseInt(currentAnimDiv.find(".scenario-duration").val()) }) } else { // If it's an animation animations.push({ type: "animation", animDict: currentAnimDiv.find(".animation-dictionary").val(), animName: currentAnimDiv.find(".animation-name").val(), animDuration: parseInt(currentAnimDiv.find(".animation-duration").val()) }) } }) animationsModal.modal("hide"); cb(animations) }) animationsModal.modal("show"); } function addAnimation(animation) { if(!animation) { animation = {}; } let fullAnimContainer = $(`
    ${getLocalizedText("menu:dynamic:animations:animation_dictionary")}
    ${getLocalizedText("menu:dynamic:animations:animation_name")}
    ${getLocalizedText("menu:dynamic:animations:animation_duration")}
    `); let scenarioContainer = fullAnimContainer.find(".scenario"); let animationContainer = fullAnimContainer.find(".animation"); let switchLabel = fullAnimContainer.find(".animation-type-label"); let switchInput = fullAnimContainer.find(".animation-type"); let removeAnimBtn = fullAnimContainer.find(".remove-anim-btn"); fullAnimContainer.find(".animation-type").change(function() { let isChecked = $(this).prop("checked"); if(isChecked) { scenarioContainer.show(); scenarioContainer.find(".form-control").prop("required", true); animationContainer.hide(); animationContainer.find(".form-control").prop("required", false); switchLabel.text("Scenario"); } else { scenarioContainer.hide(); scenarioContainer.find(".form-control").prop("required", false); animationContainer.show(); animationContainer.find(".form-control").prop("required", true); switchLabel.text("Animation"); } }) removeAnimBtn.click(function() { $(this).parent().remove(); }) if(animation && animation.type == "scenario") { switchInput.prop("checked", true).trigger("change"); } $("#animations").append(fullAnimContainer); } $("#add-animation-btn").click(function(){ addAnimation(); }) $("#harvest-add-item-btn").click(function() { addItemToHarvestable(); }); $("#harvest-animations-btn").click(function() { let editMarkerModal = $("#edit-marker-dialog-modal"); inputAnimations(editMarkerModal.data("animations"), function(animations) { editMarkerModal.data("animations", animations) }); }); $("#harvest-disappear-after-use").change(function(){ toggleDisappearsAfterUse( $(this).prop("checked") ); }); $("#harvest-choose-account-btn").click(function() { accountsDialog(accountName => { $("#harvest-minimum-account-name").val(accountName); }) }) function addItemToHarvestable(object, minQuantity = "", maxQuantity = "", secondsToHarvest = "", chances = "") { var itemDiv = $(`
    ${getLocalizedText("menu:dynamic:harvest:min_quantity")}
    ${getLocalizedText("menu:dynamic:harvest:max_quantity")}
    ${getLocalizedText("menu:dynamic:harvest:time_to_harvest")}
    ${getLocalizedText("menu:dynamic:harvest:probabilty")}

    `); $(itemDiv).find(".remove-harvestable-item-btn").click(function() { $(this).parents(".harvestable-item").remove(); }) loadChooseObjectDivs( $(itemDiv).find(".choose-object-div"), object); $("#harvest-modal-items").append(itemDiv); } $("#process-animations-btn").click(function() { let editMarkerModal = $("#edit-marker-dialog-modal"); inputAnimations(editMarkerModal.data("animations"), function(animations) { editMarkerModal.data("animations", animations) }); }) $("#process-requires-minimum-account-money").change(function() { let isEnabled = $(this).prop("checked"); $("#process-minimum-account-name-div").find("input, button").prop("disabled", !isEnabled); $("#process-minimum-account-name-div").find("input, button").prop("required", isEnabled); }); $("#process-choose-account-btn").click(function() { accountsDialog(accountName => { $("#process-minimum-account-name").val(accountName); }) }) $("#job-shop-all-jobs").change(function() { let jobRanks = $(this).data("ranks"); let jobName = $(this).val(); let allRanksSelect = $("#job-shop-all-ranks"); allRanksSelect.find(".job-shop-rank").remove(); let ranksArray = Array.isArray(jobRanks[jobName]) ? jobRanks[jobName] : Object.values(jobRanks[jobName]); ranksArray.forEach(rank => { let rankDiv = $(``); allRanksSelect.append(rankDiv); }) }) function loadAllJobsOnlinePlayers() { $.post(`https://${resName}/getAllJobsOnlinePlayers`, {}, function(jobsOnlinePlayers) { allJobsStatisticsChart.data.labels = []; allJobsStatisticsChart.data.datasets[0] = {}; allJobsStatisticsChart.data.datasets[0].data = []; allJobsStatisticsChart.data.datasets[0].label = getLocalizedText("menu:online_players"); allJobsStatisticsChart.data.datasets[0].backgroundColor = "rgba(26, 188, 156, 0.5)"; allJobsStatisticsChart.data.datasets[0].borderColor = "rgba(26, 188, 156, 0.8)"; allJobsStatisticsChart.data.datasets[0].borderWidth = 1; allJobsStatisticsChart.options.scales.y.ticks.callback = function(value, index, values) { if (Number.isInteger(value)) { return value; } } let maximumValue = 0; jobsOnlinePlayers.forEach(jobData => { allJobsStatisticsChart.data.labels.push(jobData.label); allJobsStatisticsChart.data.datasets[0].data.push(jobData.playersCount); if (jobData.playersCount > maximumValue) { maximumValue = jobData.playersCount; } }); allJobsStatisticsChart.options.scales.y.suggestedMax = maximumValue + 1; allJobsStatisticsChart.update(); }); } function loadAllJobsTotalPlayers() { $.post(`https://${resName}/getAllJobsTotalPlayers`, {}, function(jobsTotalPlayers) { allJobsStatisticsChart.data.labels = []; allJobsStatisticsChart.data.datasets[0] = {}; allJobsStatisticsChart.data.datasets[0].data = []; allJobsStatisticsChart.data.datasets[0].label = getLocalizedText("menu:total_players"); allJobsStatisticsChart.data.datasets[0].backgroundColor = "rgba(26, 188, 156, 0.5)"; allJobsStatisticsChart.data.datasets[0].borderColor = "rgba(26, 188, 156, 0.8)"; allJobsStatisticsChart.data.datasets[0].borderWidth = 1; allJobsStatisticsChart.options.scales.y.ticks.callback = function(value, index, values) { if (Number.isInteger(value)) { return value; } } let maximumValue = 0; jobsTotalPlayers.forEach(jobData => { allJobsStatisticsChart.data.labels.push(jobData.label); allJobsStatisticsChart.data.datasets[0].data.push(jobData.playersCount); if (jobData.playersCount > maximumValue) { maximumValue = jobData.playersCount; } }); allJobsStatisticsChart.options.scales.y.suggestedMax = maximumValue + 1; allJobsStatisticsChart.update(); }); } function loadAllJobsSocietyMoney() { $.post(`https://${resName}/getJobsSocietyMoney`, {}, function(jobsSocietyMoney) { allJobsStatisticsChart.data.labels = []; allJobsStatisticsChart.data.datasets[0] = {}; allJobsStatisticsChart.data.datasets[0].data = []; allJobsStatisticsChart.data.datasets[0].label = getLocalizedText("menu:society_money"); allJobsStatisticsChart.data.datasets[0].backgroundColor = "rgba(241, 196, 15, 0.4)"; allJobsStatisticsChart.data.datasets[0].borderColor = "rgba(241, 196, 15, 0.8)"; allJobsStatisticsChart.data.datasets[0].borderWidth = 1; allJobsStatisticsChart.options.scales.y.ticks.callback = function(value, index, values) { return "$" + value; } let maximumValue = 0; jobsSocietyMoney.forEach(jobData => { allJobsStatisticsChart.data.labels.push(jobData.label); allJobsStatisticsChart.data.datasets[0].data.push(jobData.money); if (jobData.money > maximumValue) { maximumValue = jobData.money; } }); allJobsStatisticsChart.options.scales.y.suggestedMax = maximumValue + maximumValue * 0.10; allJobsStatisticsChart.update(); }); } $('input[type=radio][name=all-jobs-statistics-type]').change(function() { let action = $(this).val(); switch(action) { case "online-players": { loadAllJobsOnlinePlayers(); break; } case "total-players": { loadAllJobsTotalPlayers(); break; } case "society-money": { loadAllJobsSocietyMoney(); break; } } }); function loadRanksDistrubutions(){ let jobName = $("#edit-job").data("jobName"); $.post(`https://${resName}/getRanksDistribution`, JSON.stringify({jobName: jobName }), function(rankDistribution) { jobStatisticsChart.data.labels = []; jobStatisticsChart.data.datasets[0] = {}; jobStatisticsChart.data.datasets[0].data = []; jobStatisticsChart.data.datasets[0].label = getLocalizedText("menu:chart:players_in_rank"); jobStatisticsChart.data.datasets[0].backgroundColor = "rgba(26, 188, 156, 0.5)"; jobStatisticsChart.data.datasets[0].borderColor = "rgba(26, 188, 156, 0.8)"; jobStatisticsChart.data.datasets[0].borderWidth = 1; jobStatisticsChart.options.scales.y.ticks.callback = function(value, index, values) { if (Number.isInteger(value)) { return value; } } let maximumValue = 0; rankDistribution.forEach(rankData => { jobStatisticsChart.data.labels.push(rankData.label); jobStatisticsChart.data.datasets[0].data.push(rankData.playersCount); if (rankData.playersCount > maximumValue) { maximumValue = rankData.playersCount; } }); jobStatisticsChart.options.scales.y.suggestedMax = maximumValue + 1; jobStatisticsChart.update(); }) } async function settingsTour() { const introName = "settingsTour"; if(await hasIntroBeenViewed(introName)) return; const tour = new Shepherd.Tour({ useModalOverlay: true, defaultStepOptions: { scrollTo: true } }); tour.addStep({ text: getLocalizedText("menu:intro:settings"), attachTo: { element: '#settings', on: 'right' }, buttons: [ { text: getLocalizedText("menu:intro:skip"), action: tour.cancel, secondary: true }, { text: getLocalizedText("menu:intro:next"), action: tour.next } ] }); tour.addStep({ text: getLocalizedText("menu:intro:settings_external_names"), attachTo: { element: '#settings-external-scripts-names', on: 'right' }, buttons: [ { text: getLocalizedText("menu:intro:skip"), action: tour.cancel, secondary: true }, { text: getLocalizedText("menu:intro:next"), action: tour.next } ] }); tour.addStep({ text: getLocalizedText("menu:intro:settings_modules"), attachTo: { element: '#settings-modules', on: 'right' }, buttons: [ { text: getLocalizedText("menu:intro:skip"), action: tour.cancel, secondary: true }, { text: getLocalizedText("menu:intro:next"), action: tour.next } ] }); tour.start(); registerIntroView(introName); } $("#settings-tab").click(settingsTour); async function jobTour() { const introName = "jobTour"; if(await hasIntroBeenViewed(introName)) return; const tour = new Shepherd.Tour({ useModalOverlay: true, defaultStepOptions: { scrollTo: true } }); tour.addStep({ text: getLocalizedText("menu:intro:ranks"), attachTo: { element: '#create-rank-btn', on: 'left' }, buttons: [ { text: getLocalizedText("menu:intro:skip"), action: tour.cancel, secondary: true }, { text: getLocalizedText("menu:intro:next"), action: tour.next } ] }); tour.addStep({ text: getLocalizedText("menu:intro:job_settings"), attachTo: { element: '#job-settings-tab', on: 'right' }, buttons: [ { text: getLocalizedText("menu:intro:skip"), action: tour.cancel, secondary: true }, { text: getLocalizedText("menu:intro:okay"), action: tour.next } ] }); tour.start(); registerIntroView(introName); } async function mainMenuTour() { const introName = "mainMenuTour"; if(await hasIntroBeenViewed(introName)) return; const tour = new Shepherd.Tour({ useModalOverlay: true, defaultStepOptions: { scrollTo: true } }); tour.addStep({ text: getLocalizedText("menu:intro:welcome"), buttons: [ { text: getLocalizedText("menu:intro:skip"), action: tour.cancel, secondary: true }, { text: getLocalizedText("menu:intro:next"), action: tour.next } ] }); tour.addStep({ text: getLocalizedText("menu:intro:jobs"), attachTo: { element: '#create-job-btn', on: 'left' }, buttons: [ { text: getLocalizedText("menu:intro:skip"), action: tour.cancel, secondary: true }, { text: getLocalizedText("menu:intro:next"), action: tour.next } ] }); tour.addStep({ text: getLocalizedText("menu:intro:jobs_table"), attachTo: { element: '#jobs-container', on: 'right' }, buttons: [ { text: getLocalizedText("menu:intro:skip"), action: tour.cancel, secondary: true }, { text: getLocalizedText("menu:intro:next"), action: tour.next } ] }); tour.addStep({ text: getLocalizedText("menu:intro:public_markers"), attachTo: { element: '#public-markers-tab', on: 'right' }, buttons: [ { text: getLocalizedText("menu:intro:skip"), action: tour.cancel, secondary: true }, { text: getLocalizedText("menu:intro:okay"), action: tour.next } ] }); tour.start(); registerIntroView(introName); } // [[ NEXUS ]] const voteJobRater = raterJs({ starSize: 35, element: document.querySelector("#vote-job-rater"), rateCallback: async function rateCallback(rating, done) { const jobId = $("#nexus-modal").data("jobInstance").id; const success = await $.post(`https://${resName}/nexus/rateJob`, JSON.stringify({rating, jobId})); if(success) voteJobRater.setRating(rating); done(); } }); const averageJobVotes = raterJs({ starSize: 20, readOnly: true, element: document.querySelector("#nexus-modal-job-average-rating"), }); $("#nexus-import-job-btn").click(async function() { const jobId = $("#nexus-modal").data("jobInstance").id; const response = await $.post(`https://${resName}/nexus/importJob`, JSON.stringify({jobId})); $("#nexus-modal").modal("hide"); if(response === true) refresh(); showServerResponse(response); }); let nexusDataTable = $("#nexus-jobs-container").DataTable({ "lengthMenu": [5, 10, 15, 20], "pageLength": 10, "order": [[3, 'desc'], [4, 'desc']], "createdRow": function (row, data, index) { $(row).addClass("clickable"); $(row).click(function () { const jobInstance = $(this).data("jobInstance"); showJobInstance(jobInstance); $("#nexus-modal").modal("show"); }); }, "columnDefs": [{ "defaultContent": "???", "targets": "_all" }] }); function showJobInstance(jobInstance) { $("#nexus-modal").data("jobInstance", jobInstance); $("#nexus-modal-job-listing-label").text(jobInstance.label); $("#nexus-modal-job-label").text(jobInstance.jobConfiguration.label); $("#nexus-modal-job-name").text(jobInstance.jobConfiguration.name); $("#nexus-modal-job-description").text(jobInstance.description || getLocalizedText("menu:nexus:no_description")); $("#nexus-modal-job-author").text(jobInstance.author); // Votes if(jobInstance?.votes?.total > 0) { averageJobVotes.setRating(jobInstance?.votes.averageRating); } else { averageJobVotes.setRating(0); } $("#nexus-modal-job-total-votes").text(jobInstance.votes?.total || 0); // This server vote voteJobRater.setRating(0); // Actions const actionsListDiv = $("#nexus-modal-job-actions-list"); actionsListDiv.empty(); let currentRow = null; for(let i=0; i < ACTIONS_LABELS.length; i++) { const {action, label} = ACTIONS_LABELS[i]; const actionValue = jobInstance.jobConfiguration.actions[action]; const isEnabled = action == "placeableObjects" ? actionValue.length > 0 : actionValue; if(i % 2 === 0) { actionsListDiv.append(currentRow); currentRow = null; } const emoji = isEnabled ? "✅" : "❌"; if(currentRow == null) currentRow = $("

    "); currentRow.append( i % 2 !== 0 ? `${label} ${emoji}` : `${emoji} ${label}`); } if (currentRow !== null) actionsListDiv.append(currentRow); // Ranks const ranksListDiv = $("#nexus-modal-job-ranks-list"); ranksListDiv.empty(); for(const [rank, rankInfo] of Object.entries(jobInstance.jobConfiguration.ranks)) { const rankDiv = $(`
  • ${rankInfo.label} ${rank}
  • `); ranksListDiv.append(rankDiv); } // Markers count const markersCount = jobInstance.jobMarkers ? Object.keys(jobInstance.jobMarkers).length : 0; $("#nexus-modal-job-included-markers-count").text(markersCount); } $("#upload-job-to-nexus-btn").click(async function() { const jobName = await singleJobDialog(); if(!jobName) return; $("#nexus-modal-upload").data("jobName", jobName); $("#nexus-upload-label").val(""); $("#nexus-upload-description").val(""); $("#nexus-upload-include-job-markers").prop("checked", true).change(); $("#nexus-upload-accept-tos").prop("checked", false) $("#nexus-upload-accept-sharing-data").prop("checked", false) const allJobs = await $.post(`https://${resName}/getJobsData`); const jobData = allJobs[jobName]; $("#nexus-upload-label-shared-job-label").val(jobData.label) $("#nexus-upload-label-shared-job-id").val(jobData.name) const jobMarkers = await $.post(`https://${resName}/retrieveJobMarkers`, JSON.stringify({jobName})); $("#nexus-upload-included-markers-count").val(Object.keys(jobMarkers).length) $("#nexus-modal-upload").modal("show"); }); $("#nexus-upload-include-job-markers").change(function() { const isChecked = $(this).prop("checked"); $("#nexus-upload-included-markers-count-div").toggle(isChecked); }); $("#nexus-upload-form").submit(async function(event) { if(isThereAnyErrorInForm(event)) return; const dataToUpload = { jobName: $("#nexus-modal-upload").data("jobName"), label: $("#nexus-upload-label").val(), description: $("#nexus-upload-description").val(), includeJobMarkers: $("#nexus-upload-include-job-markers").prop("checked"), } const result = await $.post(`https://${resName}/nexus/uploadJob`, JSON.stringify(dataToUpload)); if(result == true) { swal("Success", getLocalizedText("menu:nexus:upload_success"), "success"); resetNexus(); } else { swal("Error", result, "error"); } $("#nexus-modal-upload").modal("hide"); }); $("#enter-in-nexus-btn").click(async function() { $("#nexus-login").find(".spinner-border").show(); $("#enter-in-nexus-label").text("..."); const jobs = await $.get(`https://${resName}/nexus/getJobs`); if(!jobs) { swal("Error", getLocalizedText("menu:nexus:not_available"), "error"); resetNexus(); return; } nexusDataTable.clear(); for(const[_, jobInstance] of Object.entries(jobs)) { const roundedAverageRating = jobInstance?.votes?.averageRating ? Math.round(jobInstance.votes.averageRating) : 0; const ratingStars = jobInstance?.votes?.total ? "⭐".repeat(roundedAverageRating) : getLocalizedText("menu:nexus:not_rated"); const limitedDescription = jobInstance.description?.length > 30 ? jobInstance.description.substring(0, 30) + "..." : jobInstance.description; const jobMarkersCount = jobInstance.jobMarkers ? Object.keys(jobInstance.jobMarkers).length : 0; const rawRow = nexusDataTable.row.add( [jobInstance.label, limitedDescription, jobMarkersCount, ratingStars, jobInstance.votes?.total || 0, jobInstance.author] ); const rowDiv = $(rawRow.node()); $(rowDiv).data("jobInstance", jobInstance); } nexusDataTable.draw(); $("#nexus-login").hide(); $("#nexus-container").show(); }) function resetNexus() { $("#nexus-login").show(); $("#nexus-login").find(".spinner-border").hide(); $("#enter-in-nexus-label").text("Enter in Nexus"); $("#nexus-container").hide(); } async function init(version, fullConfig) { $("#job-creator-version").text(version); loadSettings(fullConfig); resetNexus() $("#job-creator").show(); await refresh(); mainMenuTour(); refreshAnnouncements(); } function exit() { // Resets current active tab (jobs is the default one) $("#job-creator").find(".nav-link, .tab-pane").each(function() { if($(this).data("isDefault") == "1") { $(this).addClass(["active", "show"]) } else { $(this).removeClass(["active", "show"]) } }) $("#job-creator").hide(); $.post(`https://${resName}/exit`) } window.addEventListener('message', (event) => { let data = event.data; let action = data.action; if (action == 'show') { init(data.version, data.fullConfig); } }) $("#close-main-btn").click(function () { exit() }) /* ░██████╗███████╗████████╗████████╗██╗███╗░░██╗░██████╗░░██████╗ ██╔════╝██╔════╝╚══██╔══╝╚══██╔══╝██║████╗░██║██╔════╝░██╔════╝ ╚█████╗░█████╗░░░░░██║░░░░░░██║░░░██║██╔██╗██║██║░░██╗░╚█████╗░ ░╚═══██╗██╔══╝░░░░░██║░░░░░░██║░░░██║██║╚████║██║░░╚██╗░╚═══██╗ ██████╔╝███████╗░░░██║░░░░░░██║░░░██║██║░╚███║╚██████╔╝██████╔╝ ╚═════╝░╚══════╝░░░╚═╝░░░░░░╚═╝░░░╚═╝╚═╝░░╚══╝░╚═════╝░╚═════╝░ */ function addJobInWhitelistForOffDutyJobs(jobName) { const listDiv = $("#settings_whitelistForOffdutyJobs"); listDiv.append(`
  • ${jobName}
  • `); listDiv.find(".remove-job").click(function() { $(this).parent().remove(); }); } $("#settings_addNewWhitelistedJobForOffduty").click(function() { let inputDiv = $("#settings_newWhitelistedJobForOffduty"); let jobName = inputDiv.val(); if(!jobName) return; inputDiv.val(""); addJobInWhitelistForOffDutyJobs(jobName); }); function getWhitelistedJobsForOffduty() { let jobs = {}; $("#settings_whitelistForOffdutyJobs").find(".job").each(function() { let jobName = $(this).data("jobName"); jobs[jobName] = true; }); return jobs; } function clearLicensesInList(type) { if(type === "driver") { var listDiv = $("#settings_drivingLicensesList"); } else if(type === "weapon") { var listDiv = $("#settings_weaponLicensesList"); } if(listDiv) { listDiv.empty(); } } function addNewLicenseInList(licenseName, type) { if(type === "driver") { var listDiv = $("#settings_drivingLicensesList"); } else if(type === "weapon") { var listDiv = $("#settings_weaponLicensesList"); } if(listDiv) { listDiv.append(`
  • ${licenseName}
  • `); listDiv.find(".remove-license").click(function() { $(this).parent().remove(); }); } } $("#settings_addNewDrivingLicenseBtn").click(function() { let drivingLicenseName = $("#settings_newDrivingLicense").val(); if(drivingLicenseName) { $("#settings_newDrivingLicense").val(""); addNewLicenseInList(drivingLicenseName, "driver"); } }) $("#settings_addNewWeaponLicenseBtn").click(function() { let weaponLicenseName = $("#settings_newWeaponLicense").val(); if(weaponLicenseName) { $("#settings_newWeaponLicense").val(""); addNewLicenseInList(weaponLicenseName, "weapon"); } }) function getSettingsLicenses(type) { if(type === "driver") { var listDiv = $("#settings_drivingLicensesList"); } else if(type === "weapon") { var listDiv = $("#settings_weaponLicensesList"); } let licenses = {}; listDiv.find(".license").each(function(index, element) { licenses[ $(element).data("license") ] = true; }) return licenses; } function getSeparatedDiscordWebhooks() { let webhooks = {}; $("#settings_specific_webhooks").find(".form-control").each(function(index, element) { let markerType = $(element).data("markerType"); let webhook = $(element).val(); if(webhook) { webhooks[markerType] = webhook; } }); return webhooks; } $("#settings").submit(async function(event) { if(isThereAnyErrorInForm(event)) return; let clientSettings = { markerDistance: parseFloat( $("#settings_markerDistance").val() ), use3Dtext: $("#settings_use3Dtext").prop("checked"), textSize: parseInt( $("#settings_textSize").val() ), textFont: parseInt( $("#settings_textFont").val() ), carLockpickTime: parseInt( $("#settings_carLockpickTime").val() ), enableAlarmWhenLockpicking: $("#settings_enableAlarmWhenLockpicking").prop("checked"), useJSFourIdCard: $("#settings_useJSFourIdCard").prop("checked"), canUseActionsMenuWhileOffDuty: $("#settings_canUseActionsMenuWhileOffDuty").prop("checked"), licenses: { driver: getSettingsLicenses("driver"), weapon: getSettingsLicenses("weapon"), }, marketSellOnePerTime: $("#settings_marketSellOnePerTime").prop("checked"), menuPosition: $("#settings_menuPosition").val(), actionsMenuKey: $("#settings_actionsMenuKey").val(), freezeWhenSoftHandcuffed: $("#settings_freezeWhenSoftHandcuffed").prop("checked"), freezeWhenHardHandcuffed: $("#settings_freezeWhenHardHandcuffed").prop("checked"), searchRequiresHandcuffState: $("#settings_searchRequiresHandcuffState").prop("checked"), targetingScript:$("#settings-targeting-script").val(), whitelistedControlsWhileHandcuffed: getAllWhitelistedControlsWhileHandcuffed(), toggleDrag: { enabled: $("#toggle-drag-enabled").prop("checked"), key: $("#toggle-drag-default-key").val() } } let sharedSettings = { allowAfkFarming: $("#settings_allowAfkFarming").prop("checked"), locale: $("#settings_locale").val(), externalScriptsNames: getIntegrationSettings(), modules: getModulesSettings(), handcuffsEnableSelfRelease: $("#settings_handcuffsEnableSelfRelease").prop("checked"), } let serverSettings = { unemployedJob: $("#settings_unemployedJob").val(), unemployedGrade: parseInt( $("#settings_unemployedGrade").val() ), acePermission: $("#settings_acePermission").val(), areDiscordLogsActive: $("#settings_isDiscordLogActive").prop("checked"), mainDiscordWebhook: $("#settings_discordWebhook").val(), specificWebhooks: getSeparatedDiscordWebhooks(), handcuffRequireItem: $("#settings_handcuffRequireItem").prop("checked"), handcuffsItemName: $("#settings_handcuffsItemName").val(), handcuffsRemoveOnUse: $("#settings_handcuffsRemoveOnUse").prop("checked"), lockpickCarRequireItem: $("#settings_lockpickCarRequireItem").prop("checked"), lockpickItemName: $("#settings_lockpickItemName").val(), lockpickRemoveOnUse: $("#settings_lockpickRemoveOnUse").prop("checked"), robbableAccounts: getRobbableAccounts(), canAlwaysCarryItem: $("#settings_canAlwaysCarryItem").prop("checked"), depositableInSafeAccounts: getDepositableInSafeAccounts(), repairVehicleRequireItem: $("#settings_repairVehicleRequireItem").prop("checked"), repairVehicleItemName: $("#settings_repairVehicleItemName").val(), repairVehicleRemoveOnUse: $("#settings_repairVehicleRemoveOnUse").prop("checked"), cleanVehicleRequireItem: $("#settings_cleanVehicleRequireItem").prop("checked"), cleanVehicleItemName: $("#settings_cleanVehicleItemName").val(), cleanVehicleRemoveOnUse: $("#settings_cleanVehicleRemoveOnUse").prop("checked"), healRequireItem: $("#settings_healRequireItem").prop("checked"), healItemName: $("#settings_healItemName").val(), healRemoveOnUse: $("#settings_healRemoveOnUse").prop("checked"), reviveRequireItem: $("#settings_reviveRequireItem").prop("checked"), reviveItemName: $("#settings_reviveItemName").val(), reviveRemoveOnuse: $("#settings_reviveRemoveOnUse").prop("checked"), enablePropertyOutfits: $("#settings_enablePropertyOutfits").prop("checked"), parkAllOwnedVehiclesOnRestart: $("#settings_parkAllOwnedVehiclesOnRestart").prop("checked"), whitelistedJobsForOffduty: getWhitelistedJobsForOffduty(), blackMoney: getBlackMoneySettings(), } const response = await $.post(`https://${resName}/saveSettings`, JSON.stringify({ clientSettings: clientSettings, serverSettings: serverSettings, sharedSettings: sharedSettings })); showServerResponse(response); refreshTranslations(sharedSettings.locale); }) async function toggleDiscordLogsInSettings(enable) { $("#settings_discordWebhook").prop("disabled", !enable); $("#settings_discordWebhook").prop("required", enable); $("#settings_specific_webhooks").find(`.form-control`).prop("disabled", !enable); if(await getInventoryScriptUsed() !== "default" || await getFramework() !== "ESX") { $("#settings_specific_webhooks").find(`.form-control[data-marker-type="stash"]`).prop("disabled", true); $("#settings_specific_webhooks").find(`.form-control[data-marker-type="armory"]`).prop("disabled", true); $("#settings_specific_webhooks").find(`.form-control[data-marker-type="safe"]`).prop("disabled", true); } } $("#settings_isDiscordLogActive").change(function() { let enabled = $(this).prop("checked"); toggleDiscordLogsInSettings(enabled); }) $(`input[type=radio][name=black-money-worth-type]`).change(function() { const worthType = $(this).val(); const isMetadata = worthType === "metadata"; $("#settings-black-money-metadata-field-id-div").toggle(isMetadata); $("#settings-black-money-metadata-field-id").prop("required", isMetadata); }); function setBlackMoneySettings(blackMoney) { $(`input[type=radio][name=black-money-worth-type][value=${blackMoney.worthType}]`).prop("checked", true).change(); setChoosenObject( $("#settings-choose-black-money-div"), blackMoney.object); $("#settings-black-money-metadata-field-id").val(blackMoney.metadataFieldId); } function getBlackMoneySettings() { return { worthType: $(`input[type=radio][name=black-money-worth-type]:checked`).val(), object: getChoosenObject( $("#settings-choose-black-money-div") ), metadataFieldId: $("#settings-black-money-metadata-field-id").val() } } async function loadSettings(fullConfig) { // CLIENT $("#settings_markerDistance").val(fullConfig.markerDistance); // 3D Text $("#settings_use3Dtext").prop("checked", fullConfig.use3Dtext); $("#settings_textSize").val(fullConfig.textSize); setTomSelectValue("#settings_textFont", fullConfig.textFont) // Targeting setTomSelectValue("#settings-targeting-script", fullConfig.targetingScript) // Black money setBlackMoneySettings(fullConfig.blackMoney); // Car lockpicking $("#settings_carLockpickTime").val(fullConfig.carLockpickTime); $("#settings_enableAlarmWhenLockpicking").prop("checked", fullConfig.enableAlarmWhenLockpicking); $("#settings_useJSFourIdCard").prop("checked", fullConfig.useJSFourIdCard); $("#settings_canUseActionsMenuWhileOffDuty").prop("checked", fullConfig.canUseActionsMenuWhileOffDuty); $("#settings_marketSellOnePerTime").prop("checked", fullConfig.marketSellOnePerTime); // Whitelisted jobs for off duty $("#off-duty-jobs-whitelist").toggle( await getFramework() == "ESX" ); $("#settings_whitelistForOffdutyJobs").empty(); for(const jobName of Object.keys(fullConfig.whitelistedJobsForOffduty || {})) { addJobInWhitelistForOffDutyJobs(jobName) } // Weapon/Driving licenses if(fullConfig.licenses) { for(const[licenseType, licenses] of Object.entries(fullConfig.licenses)) { clearLicensesInList(licenseType); Object.keys(licenses).forEach(licenseName => { addNewLicenseInList(licenseName, licenseType); }) } } // Menu position setTomSelectValue("#settings_menuPosition", fullConfig.menuPosition) // Actions key $("#settings_actionsMenuKey").val(fullConfig.actionsMenuKey); loadIntegrationsSettings(fullConfig.externalScriptsNames); loadModulesSettings(fullConfig.modules); // SHARED $("#settings_allowAfkFarming").prop("checked", fullConfig.allowAfkFarming); setTomSelectValue("#settings_locale", fullConfig.locale) // Generic $("#settings_unemployedJob").val(fullConfig.unemployedJob); $("#settings_unemployedGrade").val(fullConfig.unemployedGrade); $("#settings_acePermission").val(fullConfig.acePermission); // Discord logs webhooks $("#settings_isDiscordLogActive").prop("checked", fullConfig.areDiscordLogsActive); toggleDiscordLogsInSettings(fullConfig.areDiscordLogsActive); $("#settings_discordWebhook").val(fullConfig.mainDiscordWebhook); // Handcuffs toggleSettingsHandcuffsRequireItem(fullConfig.handcuffRequireItem); $("#settings_handcuffsItemName").val(fullConfig.handcuffsItemName) $("#settings_handcuffsRemoveOnUse").prop("checked", fullConfig.handcuffsRemoveOnUse) $("#settings_handcuffsEnableSelfRelease").prop("checked", fullConfig.handcuffsEnableSelfRelease); $("#settings_freezeWhenSoftHandcuffed").prop("checked", fullConfig.freezeWhenSoftHandcuffed); $("#settings_freezeWhenHardHandcuffed").prop("checked", fullConfig.freezeWhenHardHandcuffed); // Whitelisted controls while handcuffed $("#whitelisted-controls-while-handcuffed-list").empty(); fullConfig.whitelistedControlsWhileHandcuffed.forEach(control => { addWhitelistedControlWhileHandcuffed(control); }) // Toggle drag $("#toggle-drag-enabled").prop("checked", fullConfig.toggleDrag.enabled); $("#toggle-drag-default-key").val(fullConfig.toggleDrag.key); // Search $("#settings_searchRequiresHandcuffState").prop("checked", fullConfig.searchRequiresHandcuffState); // Lockpick toggleSettingsLockpickRequireItem(fullConfig.lockpickCarRequireItem); $("#settings_lockpickItemName").val(fullConfig.lockpickItemName) $("#settings_lockpickRemoveOnUse").prop("checked", fullConfig.lockpickRemoveOnUse) // Vehicle repair toggleSettingsVehicleRepairRequireItem(fullConfig.repairVehicleRequireItem); $("#settings_repairVehicleItemName").val(fullConfig.repairVehicleItemName); $("#settings_repairVehicleRemoveOnUse").prop("checked", fullConfig.repairVehicleRemoveOnUse); // Vehicle cleaning toggleSettingsVehicleCleaningRequireItem(fullConfig.cleanVehicleRequireItem); $("#settings_cleanVehicleItemName").val(fullConfig.cleanVehicleItemName); $("#settings_cleanVehicleRemoveOnUse").prop("checked", fullConfig.cleanVehicleRemoveOnUse); // Healing toggleSettingsHealingRequireItem(fullConfig.healRequireItem); $("#settings_healItemName").val(fullConfig.healItemName); $("#settings_healRemoveOnUse").prop("checked", fullConfig.healRemoveOnUse); // Reviving toggleSettingsRevivingRequireItem(fullConfig.reviveRequireItem); $("#settings_reviveItemName").val(fullConfig.reviveItemName); $("#settings_reviveRemoveOnUse").prop("checked", fullConfig.reviveRemoveOnuse); // Robbable accounts $("#settings_robbableAccountsList").empty(); if(fullConfig.robbableAccounts) { fullConfig.robbableAccounts.forEach(account => { addNewRobbableAccountInList(account) }); } $("#settings_canAlwaysCarryItem").prop("checked", fullConfig.canAlwaysCarryItem); // Depositable accounts $("#settings_depositableAccountsList").empty(); if(fullConfig.depositableInSafeAccounts) { fullConfig.depositableInSafeAccounts.forEach(account => { addNewDepositableAccountInList(account) }); } $("#settings_enablePropertyOutfits").prop("checked", fullConfig.enablePropertyOutfits); $("#settings_parkAllOwnedVehiclesOnRestart").prop("checked", fullConfig.parkAllOwnedVehiclesOnRestart); for(const[markerType, webhook] of Object.entries(fullConfig.specificWebhooks)) { $("#settings_specific_webhooks").find(`[data-marker-type="${markerType}"]`).val(webhook); } } $("#settingsRestoreDefaultBtn").click(async function() { if(! await confirmDeletion(getLocalizedText("menu:are_you_sure_to_restore_settings"))) return; const defaultConfiguration = await $.post(`https://${resName}/getDefaultConfiguration`); loadSettings(defaultConfiguration); }) function addNewRobbableAccountInList(accountName) { var listDiv = $("#settings_robbableAccountsList"); if(listDiv) { listDiv.append(`
  • ${accountName}
  • `); listDiv.find(".remove-account").click(function() { $(this).parent().remove(); }); } } $("#settings_addNewRobbableAccountBtn").click(function() { let robbableAccount = $("#settings_newRobbableAccount").val(); if(robbableAccount) { $("#settings_newRobbableAccount").val(""); addNewRobbableAccountInList(robbableAccount); } }) function getRobbableAccounts() { var listDiv = $("#settings_robbableAccountsList"); let robbableAccounts = []; listDiv.find(".robbable-account").each(function(index, element) { robbableAccounts.push( $(element).data("account") ); }) return robbableAccounts; } function addNewDepositableAccountInList(accountName) { var listDiv = $("#settings_depositableAccountsList"); if(listDiv) { listDiv.append(`
  • ${accountName}
  • `); listDiv.find(".remove-account").click(function() { $(this).parent().remove(); }); } } $("#settings_addNewDepositableAccountBtn").click(function() { let depositableAccount = $("#settings_newDepositableAccount").val(); if(depositableAccount) { $("#settings_newDepositableAccount").val(""); addNewDepositableAccountInList(depositableAccount); } }) function getDepositableInSafeAccounts() { var listDiv = $("#settings_depositableAccountsList"); let depositableAccounts = []; listDiv.find(".depositable-account").each(function(index, element) { depositableAccounts.push( $(element).data("account") ); }) return depositableAccounts; } // Handcuffs settings function toggleSettingsHandcuffsRequireItem(enable) { $("#settings_handcuffRequireItem").prop("checked", enable); $("#settings_handcuffsItemName").prop("disabled", !enable); $("#settings_handcuffsItemName").prop("required", enable); $("#settings_handcuffsRemoveOnUse").prop("disabled", !enable); } $("#settings_handcuffRequireItem").change(function() { toggleSettingsHandcuffsRequireItem( $("#settings_handcuffRequireItem").prop("checked") ); }) function getAllWhitelistedControlsWhileHandcuffed() { let controls = []; $("#whitelisted-controls-while-handcuffed-list").find(".control-btn").each(function(index, element) { const controlNumber = parseInt( $(element).val() ); if(controlNumber) controls.push(controlNumber); }) return controls; } function addWhitelistedControlWhileHandcuffed(control="") { const div = $(`
    `); div.find(".btn-close").click(function() { div.remove(); }); div.find(".control-btn").click(async function() { const controlNumber = await controlsDialog(); if(!controlNumber) return; $(this).val(controlNumber); }); $("#whitelisted-controls-while-handcuffed-list").append(div); } $("#add-whitelisted-control-while-handcuffed-btn").click(function() { addWhitelistedControlWhileHandcuffed(); }) // Lockpick settings function toggleSettingsLockpickRequireItem(enable) { $("#settings_lockpickCarRequireItem").prop("checked", enable); $("#settings_lockpickItemName").prop("disabled", !enable); $("#settings_lockpickItemName").prop("required", enable); $("#settings_lockpickRemoveOnUse").prop("disabled", !enable); } $("#settings_lockpickCarRequireItem").change(function() { toggleSettingsLockpickRequireItem( $(this).prop("checked") ); }) // Vehicle repair settings function toggleSettingsVehicleRepairRequireItem(enable) { $("#settings_repairVehicleRequireItem").prop("checked", enable); $("#settings_repairVehicleItemName").prop("disabled", !enable); $("#settings_repairVehicleItemName").prop("required", enable); $("#settings_repairVehicleRemoveOnUse").prop("disabled", !enable); } $("#settings_repairVehicleRequireItem").change(function() { toggleSettingsVehicleRepairRequireItem( $(this).prop("checked") ); }) // Vehicle cleaning settings function toggleSettingsVehicleCleaningRequireItem(enable) { $("#settings_cleanVehicleRequireItem").prop("checked", enable); $("#settings_cleanVehicleItemName").prop("disabled", !enable); $("#settings_cleanVehicleItemName").prop("required", enable); $("#settings_cleanVehicleRemoveOnUse").prop("disabled", !enable); } $("#settings_cleanVehicleRequireItem").change(function() { toggleSettingsVehicleCleaningRequireItem( $(this).prop("checked") ); }) // Healing settings function toggleSettingsHealingRequireItem(enable) { $("#settings_healRequireItem").prop("checked", enable); $("#settings_healItemName").prop("disabled", !enable); $("#settings_healItemName").prop("required", enable); $("#settings_healRemoveOnUse").prop("disabled", !enable); } $("#settings_healRequireItem").change(function() { toggleSettingsHealingRequireItem( $(this).prop("checked") ); }) // Reviving settings function toggleSettingsRevivingRequireItem(enable) { $("#settings_reviveRequireItem").prop("checked", enable); $("#settings_reviveItemName").prop("disabled", !enable); $("#settings_reviveItemName").prop("required", enable); $("#settings_reviveRemoveOnUse").prop("disabled", !enable); } $("#settings_reviveRequireItem").change(function() { toggleSettingsRevivingRequireItem( $(this).prop("checked") ); }) // Closes menu when clicking ESC $(document).on('keyup', function(e) { if (e.key == "Escape") { if( $("#job-creator").is(":visible") ) { exit(); } else if( $("#edit-job").is(":visible") ) { exitFromEditJob(); } } });