const resName = GetParentResourceName(); // Utils function maxTwoDecimals() { if(isNaN(this.value)) { return } let number = parseFloat(this.value); if(number) { this.value = number.toFixed(2); } } $(".max-two-decimals").change(maxTwoDecimals) 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; } // Harvestable items let harvestableItemsDatatable = $("#harvestable-items-container").DataTable( { "lengthMenu": [10, 15, 20], "createdRow": function ( row, data, index ) { $(row).addClass("clickable"); $(row).click(function() { let harvestableItemId = parseInt(data[0]); editHarvestableItem(harvestableItemId); }) }, } ); let harvestableItems = {}; function loadHarvestableItems() { $.post(`https://${resName}/getAllHarvestableItems`, {}, async function(rawHarvestableItems) { // Manually create the table to avoid incompatibilities due table indexing harvestableItems = {}; for(const[k, itemData] of Object.entries(rawHarvestableItems)) { harvestableItems[itemData.id] = itemData; } harvestableItemsDatatable.clear(); for(const[itemId, itemData] of Object.entries(harvestableItems)) { harvestableItemsDatatable.row.add([ itemId, await getItemLabel(itemData.name), itemData.minQuantity, itemData.maxQuantity, itemData.coords.x, itemData.coords.y, itemData.coords.z, ]) } harvestableItemsDatatable.draw() }) } // Harvestable items creation $("#new-harvestable-item-btn").click(function() { let harvestableModal = $("#harvestable-item-modal"); harvestableModal.data("action", "create"); harvestableModal.find("input").val(""); $("#harvestable-scale-x").val(1.5); $("#harvestable-scale-y").val(1.5); $("#harvestable-scale-z").val(1.5); $("#harvestable-icon-type").val(1); $("#harvestable-min-quantity").val(1); $("#harvestable-max-quantity").val(1); $("#harvestable-harvest-time").val(5); // Converts from edit modal to create modal $("#delete-harvestable-item-btn").hide(); $("#save-harvestable-item-btn").text( getLocalizedText("menu:create") ); $("#harvestable-item-map-blip").change(); harvestableModal.modal("show"); }) $("#harvestable-choose-item-btn").click(async function() { const itemName = await itemsDialog(); $("#harvestable-item-name").val(itemName); }) $("#harvestable-current-coords-btn").click(async function(event) { if(event.shiftKey) { const coordsInUI = { x: parseFloat( $("#harvestable-coords-x").val() ), y: parseFloat( $("#harvestable-coords-y").val() ), z: parseFloat( $("#harvestable-coords-z").val() ) } teleportToCoords(coordsInUI); return; } let coords = await getCurrentCoords() $("#harvestable-coords-x").val(coords.x); $("#harvestable-coords-y").val(coords.y); $("#harvestable-coords-z").val(coords.z); }) $("#harvestable-item-map-blip").change(function() { let enabled = $(this).prop("checked"); $("#harvestable-item-map-blip-inputs").find("input").prop("disabled", !enabled); }) $("#harvestable-form").submit(async function(event) { if(isThereAnyErrorInForm(event)) return; let harvestableItem = { name: $("#harvestable-item-name").val(), iconType: parseInt( $("#harvestable-icon-type").val() ), coords: { x: parseFloat( $("#harvestable-coords-x").val() ), y: parseFloat( $("#harvestable-coords-y").val() ), z: parseFloat( $("#harvestable-coords-z").val() ), }, scale: { x: parseFloat( $("#harvestable-scale-x").val() ), y: parseFloat( $("#harvestable-scale-y").val() ), z: parseFloat( $("#harvestable-scale-z").val() ), }, bounce: $("#harvestable-bounce").prop("checked"), followCamera: $("#harvestable-follow-camera").prop("checked"), rotate: $("#harvestable-rotate").prop("checked"), color: hexToRgb( $("#harvestable-color").val() ), opacity: parseInt( $("#harvestable-opacity").val() ), timeToHarvest: parseInt( $("#harvestable-harvest-time").val() ), minQuantity: parseInt( $("#harvestable-min-quantity").val() ), maxQuantity: parseInt( $("#harvestable-max-quantity").val() ) } let isBlipEnabled = $("#harvestable-item-map-blip").prop("checked"); if( isBlipEnabled ) { harvestableItem.blipName = $("#harvestable-item-blip-name").val(); harvestableItem.blipSprite = parseInt( $("#harvestable-item-sprite-id").val() ); harvestableItem.blipColor = parseInt( $("#harvestable-item-blip-color").val() ); harvestableItem.blipScale = parseFloat( $("#harvestable-item-blip-scale").val() ); } let harvestableItemModal = $("#harvestable-item-modal"); let action = $(harvestableItemModal).data("action"); let response = null; switch(action) { case "create": { response = await $.post(`https://${resName}/createNewHarvestableItem`, JSON.stringify(harvestableItem)); break; } case "edit": { let itemId = harvestableItemModal.data("itemId"); response = await $.post(`https://${resName}/updateHarvestableItem`, JSON.stringify({ itemId: itemId, itemData: harvestableItem })); break; } } harvestableItemModal.modal("hide"); loadHarvestableItems(); showServerResponse(response); }) // Harvestable items edit function editHarvestableItem(harvestableItemId) { let itemData = harvestableItems[harvestableItemId]; $("#harvestable-item-name").val(itemData.name); $("#harvestable-icon-type").val(itemData.iconType); $("#harvestable-coords-x").val(itemData.coords.x); $("#harvestable-coords-y").val(itemData.coords.y); $("#harvestable-coords-z").val(itemData.coords.z); $("#harvestable-scale-x").val(itemData.scale.x); $("#harvestable-scale-y").val(itemData.scale.y); $("#harvestable-scale-z").val(itemData.scale.z); $("#harvestable-bounce").prop("checked", itemData.bounce); $("#harvestable-follow-camera").prop("checked", itemData.followCamera); $("#harvestable-rotate").prop("checked", itemData.rotate); $("#harvestable-color").val( rgbToHex(itemData.color.r, itemData.color.g, itemData.color.b) ); $("#harvestable-opacity").val(itemData.opacity); $("#harvestable-harvest-time").val(itemData.timeToHarvest); $("#harvestable-min-quantity").val(itemData.minQuantity); $("#harvestable-max-quantity").val(itemData.maxQuantity); let mapBlipCheckbox = $("#harvestable-item-map-blip"); if(itemData.blipSprite) { $("#harvestable-item-blip-name").val(itemData.blipName); $("#harvestable-item-sprite-id").val(itemData.blipSprite); $("#harvestable-item-blip-color").val(itemData.blipColor); $("#harvestable-item-blip-scale").val(itemData.blipScale); mapBlipCheckbox.prop("checked", true); } else { mapBlipCheckbox.prop("checked", false); } mapBlipCheckbox.change(); let harvestableModal = $("#harvestable-item-modal"); harvestableModal.data("itemId", harvestableItemId); harvestableModal.data("action", "edit"); $("#delete-harvestable-item-btn").show(); $("#save-harvestable-item-btn").text( getLocalizedText("menu:save") ); harvestableModal.modal("show"); } // Harvestable item delete $("#delete-harvestable-item-btn").click(async function() { if(!await confirmDeletion()) return; let itemId = $("#harvestable-item-modal").data("itemId"); const response = await $.post(`https://${resName}/deleteHarvestableItem`, JSON.stringify({ itemId: itemId })); $("#harvestable-item-modal").modal("hide"); loadHarvestableItems(); showServerResponse(response); }) // Drugs Fields let drugsFieldsDatatable = $("#fields-container").DataTable({ "lengthMenu": [10, 15, 20], "createdRow": function ( row, data, index ) { $(row).addClass("clickable"); $(row).click(function() { let fieldId = parseInt(data[0]); editDrugField(fieldId); }) }, } ); let drugsFields = {}; function loadDrugsFields() { $.post(`https://${resName}/getAllDrugsFields`, {}, function(rawDrugsFields) { // Manually create the table to avoid incompatibilities due table indexing drugsFields = {}; for(const[k, fieldData] of Object.entries(rawDrugsFields)) { drugsFields[fieldData.id] = fieldData; } drugsFieldsDatatable.clear(); for(const[fieldId, fieldData] of Object.entries(drugsFields)) { drugsFieldsDatatable.row.add([ fieldId, fieldData.label, fieldData.radius, fieldData.coords.x, fieldData.coords.y, fieldData.coords.z, ]) } drugsFieldsDatatable.draw() }) } $("#new-field-btn").click(function() { let fieldModal = $("#field-modal"); fieldModal.data("action", "create"); fieldModal.find("input").val(""); $("#field-map-blip").prop("checked", false).change(); // Converts from edit modal to create modal $("#delete-field-btn").hide(); $("#save-field-btn").text( getLocalizedText("menu:create") ); $("#fields-items").empty(); addItemToField(); fieldModal.modal("show"); }) $("#field-current-coords-btn").click(async function(event) { if(event.shiftKey) { const coordsInUI = { x: parseFloat( $("#field-coords-x").val() ), y: parseFloat( $("#field-coords-y").val() ), z: parseFloat( $("#field-coords-z").val() ) } teleportToCoords(coordsInUI); return; } let coords = await getCurrentCoords(); $("#field-coords-x").val(coords.x); $("#field-coords-y").val(coords.y); $("#field-coords-z").val(coords.z); }); $("#field-required-item-choose-btn").click(async function() { const itemName = await itemsDialog(); $("#field-required-item-name").val(itemName); }) $("#field-required-item-toggle").change(function() { let enabled = $(this).prop("checked"); $("#field-required-item-choose-btn").prop("disabled", !enabled); $("#field-required-item-lose-on-use").prop("disabled", !enabled); $("#field-required-item-name").prop("disabled", !enabled).prop("required", enabled); }) async function addItemToField(itemData = {}) { let itemDiv = $(`

`); itemDiv.find(".choose-item-btn").click(async function() { const itemName = await itemsDialog(); itemDiv.find(".field-item-name").val(itemName); let itemLabel = await getItemLabel(itemName); itemDiv.find(".field-item-label").val(itemLabel); }).tooltip(); itemDiv.find(".remove-btn").click(function() { itemDiv.remove(); }) $("#fields-items").append(itemDiv); } $("#field-add-item").click(addItemToField); function getItemFieldDataFromDiv(itemDiv) { let itemData = { name: itemDiv.find(".field-item-name").val(), chances: parseInt( itemDiv.find("#field-item-chances").val() ), minQuantity: parseInt( itemDiv.find(".field-item-min-quantity").val() ), maxQuantity: parseInt( itemDiv.find(".field-item-max-quantity").val() ) } return itemData; } function getAllItemsFieldData() { let items = []; $("#fields-items").children(".item").each(function() { items.push(getItemFieldDataFromDiv( $(this) )) }) return items; } function editDrugField(fieldId) { let fieldModal = $("#field-modal"); fieldModal.data("action", "edit"); fieldModal.data("fieldId", fieldId); let fieldData = drugsFields[fieldId]; $("#field-label").val(fieldData.label); $("#field-radius").val(fieldData.radius); $("#field-coords-x").val(fieldData.coords.x); $("#field-coords-y").val(fieldData.coords.y); $("#field-coords-z").val(fieldData.coords.z); $("#field-object-model").val(fieldData.objectModel); $("#field-max-objects").val(fieldData.maxObjects); $("#field-seconds-to-harvest").val(fieldData.time); $("#delete-field-btn").show(); $("#save-field-btn").text( getLocalizedText("menu:save") ); let mapBlipCheckbox = $("#field-map-blip"); if(fieldData.blipSprite) { $("#field-blip-name").val(fieldData.blipName); $("#field-sprite-id").val(fieldData.blipSprite); $("#field-blip-color").val(fieldData.blipColor); $("#field-blip-scale").val(fieldData.blipScale); mapBlipCheckbox.prop("checked", true); } else { mapBlipCheckbox.prop("checked", false); } mapBlipCheckbox.change(); $("#field-required-item-toggle").prop("checked", fieldData.requiredItem ? true : false).change(); $("#field-required-item-name").val(fieldData.requiredItem?.name || ""); $("#field-required-item-lose-on-use").prop("checked", fieldData.requiredItem?.loseOnUse ?? false); $("#fields-items").empty(); if(fieldData.items) { for(const itemData of fieldData.items) { addItemToField(itemData); } } fieldModal.modal("show"); } $("#field-map-blip").change(function() { let enabled = $(this).prop("checked"); $("#field-map-blip-inputs").find("input").prop("disabled", !enabled); }) $("#field-form").submit(async function(event) { if(isThereAnyErrorInForm(event)) return; let fieldData = { label: $("#field-label").val(), radius: parseInt( $("#field-radius").val() ), coords: { x: parseFloat( $("#field-coords-x").val() ), y: parseFloat( $("#field-coords-y").val() ), z: parseFloat( $("#field-coords-z").val() ) }, items: getAllItemsFieldData(), objectModel: $("#field-object-model").val(), maxObjects: parseInt( $("#field-max-objects").val() ), time: parseInt( $("#field-seconds-to-harvest").val() ), requiredItem: $("#field-required-item-toggle").prop("checked") ? { name: $("#field-required-item-name").val(), loseOnUse: $("#field-required-item-lose-on-use").prop("checked") } : undefined } let isBlipEnabled = $("#field-map-blip").prop("checked"); if( isBlipEnabled ) { fieldData.blipName = $("#field-blip-name").val(); fieldData.blipSprite = parseInt( $("#field-sprite-id").val() ); fieldData.blipColor = parseInt( $("#field-blip-color").val() ); fieldData.blipScale = parseFloat( $("#field-blip-scale").val() ); } let fieldModal = $("#field-modal"); let action = fieldModal.data("action"); let response = null; switch(action) { case "create": { response = await $.post(`https://${resName}/createNewField`, JSON.stringify(fieldData)) break; } case "edit": { const fieldId = fieldModal.data("fieldId"); response = await $.post(`https://${resName}/updateField`, JSON.stringify({fieldId: fieldId, fieldData: fieldData})); break; } } showServerResponse(response); fieldModal.modal("hide"); loadDrugsFields() }) $("#delete-field-btn").click(async function() { if(!await confirmDeletion()) return; let fieldId = $("#field-modal").data("fieldId"); const response = await $.post(`https://${resName}/deleteField`, JSON.stringify({fieldId: fieldId})) showServerResponse(response); $("#field-modal").modal("hide"); loadDrugsFields(); }) // Craftings creation let craftingRecipesDatatable = $("#crafting-recipes-container").DataTable( { "lengthMenu": [10, 15, 20], "createdRow": function ( row, data, index ) { $(row).addClass("clickable"); $(row).click(function() { let craftingId = parseInt(data[0]); editCraftingRecipe(craftingId); }) }, } ); let craftingRecipes = {}; function loadCraftingRecipes() { $.post(`https://${resName}/getAllCraftingRecipes`, {}, function(rawCraftingRecipes) { // Manually create the table to avoid incompatibilities due table indexing craftingRecipes = {}; for(const[k, craftingRecipe] of Object.entries(rawCraftingRecipes)) { craftingRecipes[craftingRecipe.id] = craftingRecipe; } craftingRecipesDatatable.clear(); for(const[craftingId, craftingRecipe] of Object.entries(craftingRecipes)) { craftingRecipesDatatable.row.add([ craftingId, craftingRecipe.name, craftingRecipe.resultItems.map(resultItem => `${resultItem.itemName}`).join(", "), craftingRecipe.time ]) } craftingRecipesDatatable.draw() }) } $("#new-crafting-btn").click(function() { let craftingRecipeModal = $("#crafting-recipe-modal"); craftingRecipeModal.data("action", "create"); craftingRecipeModal.modal("show"); $("#crafting-recipe-result-items-container").empty(); $("#crafting-recipe-ingredients-container").empty(); $("#crafting-recipe-perfect-recipe-reward-container").empty(); // Adapts the modal to creation instead of edit $("#crafting-recipe-modal-confirm-btn").text( getLocalizedText("menu:create") ); $("#delete-crafting-recipe-btn").hide(); $("#crafting-recipe-modal").find("input").val(""); // Adds one empty result item and ingredient addResultItemInCraftingRecipe(); addIngredientInCraftingRecipe(); addRewardItemInCraftingRecipe(); }); // Adds a result item in the crafting recipe function addResultItemInCraftingRecipe(itemName = "", itemQuantity = 1) { let craftingRecipeContainer = $("#crafting-recipe-result-items-container"); let resultItemDiv = $(`
`); resultItemDiv.find(".choose-item-btn").click(async function() { const itemName = await itemsDialog(); resultItemDiv.find(".result-item-name").val(itemName); }) resultItemDiv.find(".remove-result-item-btn").click(function() { resultItemDiv.remove(); }) craftingRecipeContainer.append(resultItemDiv); } $("#crafting-recipe-add-result-item-btn").click(function() { addResultItemInCraftingRecipe(); }) function addIngredientInCraftingRecipe(ingredientName = "", ingredientMinQuantity = 1, ingredientMaxQuantity = 3, ingredientPerfectQuantity = 2, loseOnUse = true) { let ingredientsContainer = $("#crafting-recipe-ingredients-container"); let ingredientDiv = $(`

`); ingredientDiv.find(".choose-item-btn").click(async function() { const itemName = await itemsDialog(); ingredientDiv.find(".ingredient-item-name").val(itemName); }).tooltip(); ingredientDiv.find(".remove-ingredient-btn").click(function() { ingredientDiv.remove(); }) ingredientsContainer.append(ingredientDiv); } $("#crafting-recipe-add-ingredient-btn").click(function() { addIngredientInCraftingRecipe(); }) // Get the data from crafting recipe modal function getCraftingRecipeData() { let resultItems = []; $("#crafting-recipe-result-items-container").children(".result-item").each(function() { let resultItem = { itemName: $(this).find(".result-item-name").val(), itemQuantity: parseInt( $(this).find(".result-item-quantity").val() ) } resultItems.push(resultItem); }); let ingredients = []; $("#crafting-recipe-ingredients-container").children(".ingredient").each(function() { let ingredient = { ingredientItemName: $(this).find(".ingredient-item-name").val(), ingredientMinQuantity: parseInt( $(this).find(".ingredient-min-quantity").val() ), ingredientMaxQuantity: parseInt( $(this).find(".ingredient-max-quantity").val() ), ingredientPerfectQuantity: parseInt( $(this).find(".ingredient-perfect-quantity").val() ), loseOnUse: $(this).find(".form-check-input").is(":checked") } ingredients.push(ingredient); }); let perfectRecipeReward = []; $("#crafting-recipe-perfect-recipe-reward-container").children(".reward-item").each(function() { let perfectRecipeRewardItem = { itemName: $(this).find(".reward-item-name").val(), itemQuantity: parseInt( $(this).find(".reward-item-quantity").val() ) } perfectRecipeReward.push(perfectRecipeRewardItem); }); let timeToCraft = parseInt( $("#crafting-recipe-time-to-craft").val() ); let craftName = $("#crafting-recipe-name").val(); return { resultItems: resultItems, ingredients: ingredients, perfectRecipeReward: perfectRecipeReward, time: timeToCraft, name: craftName } } // Saves the new crafting recipe created $("#crafting-recipe-form").submit(async function(event) { if(isThereAnyErrorInForm(event)) return; let craftingRecipeData = getCraftingRecipeData(); let craftingRecipeModal = $("#crafting-recipe-modal"); let action = craftingRecipeModal.data("action"); let response = null; switch(action) { case "create": { response = await $.post(`https://${resName}/createNewCraftingRecipe`, JSON.stringify(craftingRecipeData)) break; } case "edit": { let craftingId = craftingRecipeModal.data("craftingId"); response = await $.post(`https://${resName}/updateCraftingRecipe`, JSON.stringify({craftingId: craftingId, craftingRecipe: craftingRecipeData})); break; } } showServerResponse(response); craftingRecipeModal.modal("hide"); loadCraftingRecipes(); }) // To edit an existing crafting recipe function editCraftingRecipe(craftingId) { // Adapts the modal to edit instead of create $("#delete-crafting-recipe-btn").show(); $("#crafting-recipe-modal-confirm-btn").text( getLocalizedText("menu:save") ); let craftingData = craftingRecipes[craftingId]; $("#crafting-recipe-time-to-craft").val(craftingData.time); $("#crafting-recipe-name").val(craftingData.name); $("#crafting-recipe-result-items-container").empty(); $("#crafting-recipe-ingredients-container").empty(); $("#crafting-recipe-perfect-recipe-reward-container").empty(); for (let resultItem of craftingData.resultItems) { addResultItemInCraftingRecipe(resultItem.itemName, resultItem.itemQuantity); } for (let rewardItem of craftingData.perfectRecipeReward) { addRewardItemInCraftingRecipe(rewardItem.itemName, rewardItem.itemQuantity); } for (let ingredient of craftingData.ingredients) { addIngredientInCraftingRecipe(ingredient.ingredientItemName, ingredient.ingredientMinQuantity, ingredient.ingredientMaxQuantity, ingredient.ingredientPerfectQuantity, ingredient.loseOnUse); } let craftingRecipeModal = $("#crafting-recipe-modal"); craftingRecipeModal.modal("show"); craftingRecipeModal.data("action", "edit"); craftingRecipeModal.data("craftingId", craftingId); } // Deletes crafting recipe $("#delete-crafting-recipe-btn").click(async function() { if(!await confirmDeletion()) return; let craftingId = $("#crafting-recipe-modal").data("craftingId"); const response = await $.post(`https://${resName}/deleteCraftingRecipe`, JSON.stringify({craftingId: craftingId})); showServerResponse(response); $("#crafting-recipe-modal").modal("hide"); loadCraftingRecipes(); }) // Adds a reward item in the crafting recipe for perfect crafting function addRewardItemInCraftingRecipe(itemName = "", itemQuantity = 1) { let rewardsContainer = $("#crafting-recipe-perfect-recipe-reward-container"); let rewardItemDiv = $(`
`); rewardItemDiv.find(".choose-item-btn").click(async function() { const itemName = await itemsDialog(); rewardItemDiv.find(".reward-item-name").val(itemName); }) rewardItemDiv.find(".remove-reward-item-btn").click(function() { rewardItemDiv.remove(); }) rewardsContainer.append(rewardItemDiv); } $("#crafting-recipe-add-reward-item-btn").click(function() { addRewardItemInCraftingRecipe(); }) // Laboratories let laboratoriesDatatable = $("#laboratories-container").DataTable( { "lengthMenu": [10, 15, 20], "createdRow": function ( row, data, index ) { $(row).addClass("clickable"); $(row).click(function() { let laboratoryId = parseInt(data[0]); editLaboratory(laboratoryId); }) }, } ); let laboratories = {}; function loadLaboratories() { $.post(`https://${resName}/getAllLaboratories`, {}, function(rawLaboratories) { // Manually create the table to avoid incompatibilities due table indexing laboratories = {}; for(const[k, laboratoryData] of Object.entries(rawLaboratories)) { laboratories[laboratoryData.id] = laboratoryData; } laboratoriesDatatable.clear(); for(const[laboratoryId, laboratoryData] of Object.entries(laboratories)) { laboratoriesDatatable.row.add([ laboratoryId, laboratoryData.name, laboratoryData.coords.x, laboratoryData.coords.y, laboratoryData.coords.z, ]) } laboratoriesDatatable.draw() }) } // Create new laboratory $("#new-laboratory-btn").click(function() { let laboratoryModal = $("#laboratory-modal"); laboratoryModal.modal("show"); laboratoryModal.data("action", "create"); $("#laboratory-name").val(""); $("#laboratory-coords-x").val(""); $("#laboratory-coords-y").val(""); $("#laboratory-coords-z").val(""); $("#laboratory-scale-x").val("1.5"); $("#laboratory-scale-y").val("1.5"); $("#laboratory-scale-z").val("0.5"); $("#laboratory-icon-type").val("1"); $("#laboratory-opacity").val("100"); $("#laboratory-map-blip").prop("checked", false).change(); // Resets stuff related to allowed jobs (all allowed) setLaboratoryAllowedJobsText(false); $("#laboratory-allowed-jobs").data("jobs", false); // Resets stuff related to allowed recipes $("#laboratory-allowed-crafting-recipes").text(getLocalizedText("menu:no_crafting_recipe_allowed")); $("#laboratory-allowed-crafting-recipes").data("craftingRecipes", {}); // Adapts the modal from edit mode to create mode $("#delete-laboratory-btn").hide(); $("#laboratory-modal-confirm-btn").text( getLocalizedText("menu:create") ); }) function setLaboratoryAllowedJobsText(jobs) { if(jobs === false) { $("#laboratory-allowed-jobs").text(getLocalizedText("menu:all_jobs_allowed")); } else if(Object.keys(jobs).length == 0) { $("#laboratory-allowed-jobs").text(getLocalizedText("menu:no_job_allowed")); } else { $("#laboratory-allowed-jobs").text( Object.keys(jobs).join(", ") ); } } $("#laboratory-choose-jobs").click(async function() { const oldJobs = $("#laboratory-allowed-jobs").data("jobs"); const jobs = await jobsDialog(oldJobs); setLaboratoryAllowedJobsText(jobs); $("#laboratory-allowed-jobs").data("jobs", jobs) }) // Dialog that shows all crafting recipes and returns the selected ones function craftingRecipesDialog(cb) { let inputCraftingRecipesModal = $("#input-crafting-recipes-dialog-modal") inputCraftingRecipesModal.modal("show"); $("#input-crafting-recipes-search").val(""); $.post(`https://${resName}/getAllCraftingRecipes`, JSON.stringify({}), function (craftingRecipes) { let craftingRecipesListDiv = $("#crafting-recipes-list"); craftingRecipesListDiv.empty(); for(const[k, craftingRecipeData] of Object.entries(craftingRecipes)) { let craftingRecipeDiv = $(`
`); craftingRecipesListDiv.append(craftingRecipeDiv); } // Unbinds the button and rebinds it to callback the selected crafting recipes $("#input-crafting-recipes-confirm-btn").unbind().click(function() { let selectedCraftingRecipes = {}; craftingRecipesListDiv.find("input:checked").each(function() { let recipeId = $(this).val(); selectedCraftingRecipes[recipeId] = true; }); inputCraftingRecipesModal.modal("hide"); cb(selectedCraftingRecipes); }) }); } $("#input-crafting-recipe-search").on("keyup", function() { let text = $(this).val().toLowerCase(); $("#crafting-recipes-list .form-check").filter(function() { $(this).toggle($(this).text().toLowerCase().indexOf(text) > -1) }); }) // Choose crafting recipes for laboratory $("#laboratory-choose-recipes").click(function() { craftingRecipesDialog((selectedRecipes) => { if(Object.keys(selectedRecipes).length == 0) { $("#laboratory-allowed-crafting-recipes").text(getLocalizedText("menu:no_crafting_recipe_allowed")); } else { $("#laboratory-allowed-crafting-recipes").text(Object.keys(selectedRecipes).map(recipeId => craftingRecipes[recipeId].name).join(", ")); } $("#laboratory-allowed-crafting-recipes").data("recipes", selectedRecipes); }) }) // Sets current coords for laboratory $("#laboratory-current-coords-btn").click(async function(event) { if(event.shiftKey) { const coordsInUI = { x: parseFloat( $("#laboratory-coords-x").val() ), y: parseFloat( $("#laboratory-coords-y").val() ), z: parseFloat( $("#laboratory-coords-z").val() ) } teleportToCoords(coordsInUI); return; } const coords = await getCurrentCoords(); $("#laboratory-coords-x").val(coords.x); $("#laboratory-coords-y").val(coords.y); $("#laboratory-coords-z").val(coords.z); }) // To edit an existing laboratory function editLaboratory(laboratoryId) { let laboratoryModal = $("#laboratory-modal"); laboratoryModal.data("laboratoryId", laboratoryId); laboratoryModal.data("action", "edit"); let laboratoryData = laboratories[laboratoryId]; $("#laboratory-name").val(laboratoryData.name); $("#laboratory-coords-x").val(laboratoryData.coords.x); $("#laboratory-coords-y").val(laboratoryData.coords.y); $("#laboratory-coords-z").val(laboratoryData.coords.z); $("#laboratory-scale-x").val(laboratoryData.scale.x); $("#laboratory-scale-y").val(laboratoryData.scale.y); $("#laboratory-scale-z").val(laboratoryData.scale.z); $("#laboratory-bounce").prop("checked", laboratoryData.bounce); $("#laboratory-follow-camera").prop("checked", laboratoryData.followCamera); $("#laboratory-rotate").prop("checked", laboratoryData.rotate); $("#laboratory-icon-type").val(laboratoryData.iconType); $("#laboratory-color").val( rgbToHex(laboratoryData.color.r, laboratoryData.color.g, laboratoryData.color.b) ); $("#laboratory-opacity").val(laboratoryData.opacity); let mapBlipCheckbox = $("#laboratory-map-blip"); if(laboratoryData.blipSprite) { $("#laboratory-blip-name").val(laboratoryData.blipName); $("#laboratory-sprite-id").val(laboratoryData.blipSprite); $("#laboratory-blip-color").val(laboratoryData.blipColor); $("#laboratory-blip-scale").val(laboratoryData.blipScale); mapBlipCheckbox.prop("checked", true); } else { mapBlipCheckbox.prop("checked", false); } mapBlipCheckbox.change(); setLaboratoryAllowedJobsText(laboratoryData.allowedJobs); $("#laboratory-allowed-jobs").data("jobs", laboratoryData.allowedJobs); let sanitizedAllowedRecipes = {}; Object.keys(laboratoryData.allowedRecipes).forEach(recipeId => { if(recipeId == 0) { recipeId = 1; } sanitizedAllowedRecipes[recipeId] = true; }); $("#laboratory-allowed-crafting-recipes").text( Object.keys(sanitizedAllowedRecipes).map(recipeId => craftingRecipes[recipeId] ? craftingRecipes[recipeId].name : null).join(", ") ); $("#laboratory-allowed-crafting-recipes").data("recipes", sanitizedAllowedRecipes); // Adatps the modal from create mode to edit mode $("#delete-laboratory-btn").show(); $("#laboratory-modal-confirm-btn").text( getLocalizedText("menu:save") ); laboratoryModal.modal("show"); } // To delete an existing laboratory $("#delete-laboratory-btn").click(async function() { if(!await confirmDeletion()) return; let laboratoryId = $("#laboratory-modal").data("laboratoryId"); if(laboratoryId == null) return; const response = await $.post(`https://${resName}/deleteLaboratory`, JSON.stringify({ laboratoryId: laboratoryId })); showServerResponse(response); $("#laboratory-modal").modal("hide"); loadLaboratories(); }) $("#laboratory-map-blip").change(function() { let enabled = $(this).prop("checked"); $("#laboratory-map-blip-inputs").find("input").prop("disabled", !enabled); }) // Gets the laboratory data from its modal function getLaboratoryData() { let laboratoryData = { name: $("#laboratory-name").val(), coords: { x: parseFloat( $("#laboratory-coords-x").val() ), y: parseFloat( $("#laboratory-coords-y").val() ), z: parseFloat( $("#laboratory-coords-z").val() ) }, iconType: parseInt( $("#laboratory-icon-type").val() ), scale: { x: parseFloat( $("#laboratory-scale-x").val() ), y: parseFloat( $("#laboratory-scale-y").val() ), z: parseFloat( $("#laboratory-scale-z").val() ), }, bounce: $("#laboratory-bounce").prop("checked"), followCamera: $("#laboratory-follow-camera").prop("checked"), rotate: $("#laboratory-rotate").prop("checked"), color: hexToRgb( $("#laboratory-color").val() ), opacity: parseInt( $("#laboratory-opacity").val() ), allowedJobs: $("#laboratory-allowed-jobs").data("jobs"), allowedRecipes: $("#laboratory-allowed-crafting-recipes").data("recipes") || {} } let isBlipEnabled = $("#laboratory-map-blip").prop("checked"); if( isBlipEnabled ) { laboratoryData.blipName = $("#laboratory-blip-name").val(); laboratoryData.blipSprite = parseInt( $("#laboratory-sprite-id").val() ); laboratoryData.blipColor = parseInt( $("#laboratory-blip-color").val() ); laboratoryData.blipScale = parseFloat( $("#laboratory-blip-scale").val() ); } return laboratoryData; } // Saves laboratory data $("#laboratory-form").submit(async function(event) { if(isThereAnyErrorInForm(event)) return; let laboratoryModal = $("#laboratory-modal"); let laboratoryData = getLaboratoryData(); let action = laboratoryModal.data("action"); let response = null; switch(action) { case "create": { response = await $.post(`https://${resName}/createNewLaboratory`, JSON.stringify(laboratoryData)) break; } case "edit": { let laboratoryId = laboratoryModal.data("laboratoryId"); response = await $.post(`https://${resName}/updateLaboratory`, JSON.stringify({laboratoryId: laboratoryId, laboratoryData: laboratoryData})) break; } } showServerResponse(response); laboratoryModal.modal("hide"); loadLaboratories(); }) function addRequiredItemInPocketCrafting(pocketCraftingDiv, itemName = "", itemQuantity = 1, loseOnUse = true) { let requiredItemsContainer = pocketCraftingDiv.find(".pocket-crafting-required-items"); let requiredItemDiv = $(`
`); requiredItemDiv.find(".choose-item-btn").click(async function() { const itemName = await itemsDialog(); requiredItemDiv.find(".required-item-name").val(itemName); }).tooltip(); requiredItemDiv.find(".remove-required-item-btn").click(function() { requiredItemDiv.remove(); }); requiredItemsContainer.append(requiredItemDiv); } async function addPocketCrafting(itemName, pocketCraftingData, isNew = false) { const itemLabel = await getItemLabel(itemName) || "Unknown item - " + itemName; const div = $(`

${getLocalizedText("menu:you_have_to_use")} '${itemLabel}' ${getLocalizedText("menu:to_start_the_crafting")} (${itemName})

${getLocalizedText("menu:to_receive")}

${getLocalizedText("menu:pocket_craftings:required_items")}


`); div.find(".choose-item-btn").click(async function() { const itemName = await itemsDialog(); div.find(".result-item-name").val(itemName); }).tooltip(); div.find(".add-required-item-btn").click(function() { addRequiredItemInPocketCrafting(div); }); div.find(".delete-pocket-crafting").click(function() { div.remove(); }); if(pocketCraftingData) { div.find(".result-item-name").val(pocketCraftingData.resultItem.name); div.find(".item-quantity").val(pocketCraftingData.resultItem.quantity); div.find(".time-to-craft").val(pocketCraftingData.timeToCraft); for(const requiredItem of pocketCraftingData.requiredItems) { addRequiredItemInPocketCrafting(div, requiredItem.name, requiredItem.quantity, requiredItem.loseOnUse); } } if(isNew) { div.find(".title").append(` - ${ getLocalizedText("menu:effects:may_need_restart") }`) } $("#pocket-craftings-list").append(div); } // Pocket sellings $("#create-new-pocket-crafting-btn").click(async function() { const itemName = await itemsDialog(getLocalizedText("menu:choose_the_item_that_will_start_pocket_crafting_on_use")); if(!itemName) return; addPocketCrafting(itemName, null, true); }); function getAllPocketCraftings() { const pocketCraftings = {}; $("#pocket-craftings-list").find(".pocket-crafting").each(function() { const itemName = $(this).data("itemToUse"); const pocketCrafting = { resultItem: { name: $(this).find(".result-item-name").val(), quantity: parseInt($(this).find(".item-quantity").val()) }, timeToCraft: parseInt($(this).find(".time-to-craft").val()), requiredItems: [] }; $(this).find(".required-item").each(function() { const requiredItem = { name: $(this).find(".required-item-name").val(), quantity: parseInt($(this).find(".required-item-quantity").val()), loseOnUse: $(this).find(".form-check-input").prop("checked") }; pocketCrafting.requiredItems.push(requiredItem); }); pocketCraftings[itemName] = pocketCrafting; }); return pocketCraftings; } $("#pocket-craftings").submit(async function(event) { if(isThereAnyErrorInForm(event)) return; let serverSettings = { pocketCraftings: getAllPocketCraftings(), } const response = await $.post(`https://${resName}/saveSettings`, JSON.stringify({ clientSettings: {}, serverSettings: serverSettings, sharedSettings: {} })); showServerResponse(response); }); // Plane selling $("#plane-selling-current-coords-btn").click(async function(event) { if(event.shiftKey) { const coordsInUI = { x: parseFloat( $("#plane-selling-coords-x").val() ), y: parseFloat( $("#plane-selling-coords-y").val() ), z: parseFloat( $("#plane-selling-coords-z").val() ) } teleportToCoords(coordsInUI); return; } const coords = await getCurrentCoords(); $("#plane-selling-coords-x").val(coords.x); $("#plane-selling-coords-y").val(coords.y); $("#plane-selling-coords-z").val(coords.z); }) function togglePlaneWholeOcean() { let enabled = $("#plane-use-the-whole-ocean").prop("checked"); $("#plane-selling-coords").find("input").prop("disabled", enabled); } $("#plane-use-the-whole-ocean").change(togglePlaneWholeOcean); $("#plane-add-new-drug").click(function() { addAcceptableDrugToDiv("#plane-selling-acceptable-drugs"); }) // Enables/Disables all inputs for plane selling function togglePlaneSelling() { let enable = $("#enable-plane-selling").prop("checked"); $("#selling-plane").find("input, button").not("#enable-plane-selling").prop("disabled", !enable); } $("#enable-plane-selling").change(togglePlaneSelling); // Boat selling $("#boat-selling-current-coords-btn").click(async function(event) { if(event.shiftKey) { const coordsInUI = { x: parseFloat( $("#boat-selling-coords-x").val() ), y: parseFloat( $("#boat-selling-coords-y").val() ), z: parseFloat( $("#boat-selling-coords-z").val() ) } teleportToCoords(coordsInUI); return; } const coords = await getCurrentCoords(); $("#boat-selling-coords-x").val(coords.x); $("#boat-selling-coords-y").val(coords.y); $("#boat-selling-coords-z").val(coords.z); }); function toggleBoatWholeOcean() { let enabled = $("#boat-use-the-whole-ocean").prop("checked"); $("#boat-selling-coords").find("input").prop("disabled", enabled); } $("#boat-use-the-whole-ocean").change(toggleBoatWholeOcean); $("#boat-add-new-drug").click(function() { addAcceptableDrugToDiv("#boat-selling-acceptable-drugs"); }) function toggleBoatSelling() { let enable = $("#enable-boat-selling").prop("checked"); $("#selling-boat").find("input, button").not("#enable-boat-selling").prop("disabled", !enable); } $("#enable-boat-selling").change(toggleBoatSelling); // NPC Selling function toggleNpcSelling() { let enable = $("#enable-npc-selling").prop("checked"); $("#selling-npc").find("input, button").not("#enable-npc-selling").prop("disabled", !enable); } $("#enable-npc-selling").change(toggleNpcSelling); function addAcceptableDrugToDiv(drugsListDiv, drugName = "", minPrice = 500, maxPrice = 1000) { let drugDiv = $(`
`) drugDiv.find(".choose-item-btn").click(async function() { const itemName = await itemsDialog(); drugDiv.find(".drug-name").val(itemName); }).tooltip(); drugDiv.find(".remove-btn").click(function() { drugDiv.remove(); }); $(drugsListDiv).append(drugDiv); } function fillAcceptableDrugsForDiv(drugsListDiv, drugs) { $(drugsListDiv).empty(); if(drugs) { for(drug of drugs) { addAcceptableDrugToDiv(drugsListDiv, drug.name, drug.minPrice, drug.maxPrice); } } } function getAcceptableDrugFromDiv(drugsListDiv) { let drugs = []; $(drugsListDiv).find(".drug").each(function() { let drug = { name: $(this).find(".drug-name").val(), minPrice: parseInt( $(this).find(".drug-min-price").val() ), maxPrice: parseInt( $(this).find(".drug-max-price").val() ), } drugs.push(drug); }) return drugs; } $("#npc-add-new-drug").click(function() { addAcceptableDrugToDiv("#npc-selling-acceptable-drugs"); }) $("#npc-selling-command-is-enabled").change(function() { const enabled = $(this).prop("checked"); $("#npc-selling-command").prop("disabled", !enabled); $("#npc-selling-command-has-to-spawn-npc").prop("disabled", !enabled); }); // Save selling $("#selling").submit(async function(event) { if(isThereAnyErrorInForm(event)) return; let clientSettings = { // Boat and plane selling heightToSell: parseInt( $("#minimum-plane-height").val() ), sellUseWholeOcean: { plane: $("#plane-use-the-whole-ocean").prop("checked"), boat: $("#boat-use-the-whole-ocean").prop("checked") }, sellArea: { plane: { coords: { x: parseFloat( $("#plane-selling-coords-x").val() ), y: parseFloat( $("#plane-selling-coords-y").val() ), z: parseFloat( $("#plane-selling-coords-z").val() ) }, radius: parseFloat( $("#plane-selling-coords-radius").val() ) }, boat: { coords: { x: parseFloat( $("#boat-selling-coords-x").val() ), y: parseFloat( $("#boat-selling-coords-y").val() ), z: parseFloat( $("#boat-selling-coords-z").val() ) }, radius: parseFloat( $("#boat-selling-coords-radius").val() ) } }, sellShowRadius: { plane: $("#plane-show-radius-while-selling").prop("checked"), boat: $("#boat-show-radius-while-selling").prop("checked") }, // Narcos selling narcosModel: $("#narcos-model").val(), showNarcosBlip: $("#enable-narcos-blip").prop("checked"), narcosBlip: { name: $("#narcos-selling-blip-name").val(), color: parseInt( $("#narcos-selling-blip-color").val() ), scale: parseFloat( $("#narcos-selling-blip-scale").val() ), sprite: parseInt( $("#narcos-selling-blip-sprite").val() ) }, // Pushers selling pusherModel: $("#pushers-model").val(), showPushersBlips: $("#enable-pushers-blip").prop("checked"), pusherBlip: { name: $("#pushers-selling-blip-name").val(), color: parseInt( $("#pushers-selling-blip-color").val() ), scale: parseFloat( $("#pushers-selling-blip-scale").val() ), sprite: parseInt( $("#pushers-selling-blip-sprite").val() ) } } let serverSettings = { rewards: { plane: getRewardDivData("#plane-selling-reward-div"), boat: getRewardDivData("#boat-selling-reward-div"), npc: getRewardDivData("#npc-selling-reward-div"), narcos: getRewardDivData("#narcos-selling-reward-div"), pushers: getRewardDivData("#pushers-selling-reward-div") }, // Plane selling planeAcceptableDrugs: getAcceptableDrugFromDiv("#plane-selling-acceptable-drugs"), planeSellingMinimumPolice: parseInt( $("#plane-minimum-police").val() ), // Boat selling boatAcceptableDrugs: getAcceptableDrugFromDiv("#boat-selling-acceptable-drugs"), boatSellingMinimumPolice: parseInt( $("#boat-minimum-police").val() ), // NPC selling minNPCSellQuantity: parseInt( $("#npc-selling-min-quantity").val() ), maxNPCSellQuantity: parseInt( $("#npc-selling-max-quantity").val() ), sellToNPCChancesToAccept: parseInt( $("#npc-accept-chances").val() ), maxNPCsSellableDrugQuantity: parseInt( $("#npc-max-drug-quantity").val() ), npcAcceptableDrugs: getAcceptableDrugFromDiv("#npc-selling-acceptable-drugs"), npcSellingMinimumPolice: parseInt( $("#npc-minimum-police").val() ), npcAlertPoliceChances: parseInt( $("#npc-alert-police-chances").val() ), canNPCRobPlayer: $("#npc-can-rob-player").prop("checked"), canNPCAttackPlayer: $("#npc-can-attack-player").prop("checked"), // Narcos selling narcosBuyerLocations: getNarcosBuyerLocations(), narcosLocationChangeTime: parseInt( $("#narcos-location-change").val() ), narcosCallPoliceChances: parseInt( $("#narcos-police-alert-chances").val() ), narcosAcceptsOnlyOneBuyerPerLocation: $("#narcos-accepts-only-one-buyer-per-location").prop("checked"), narcosNeededDrugs: getNarcosDrugs(), narcosSellingMinimumPolice: parseInt( $("#narcos-minimum-police").val() ), // Pushers selling pushersCallPoliceChances: parseInt( $("#pushers-alert-police-chances").val() ), pushers: getPushers(), pushersSellingMinimumPolice: parseInt( $("#pushers-minimum-police").val() ), } let sharedSettings = { enableAirplaneSell: $("#enable-plane-selling").prop("checked"), enableBoatSell: $("#enable-boat-selling").prop("checked"), timeToSellInPlane: parseInt( $("#time-to-sell-in-plane").val() ), timeToSellInBoat: parseInt( $("#time-to-sell-in-boat").val() ), alarmPoliceInPlane: $("#enable-plane-police-alert").prop("checked"), alarmPoliceInBoat: $("#enable-boat-police-alert").prop("checked"), // NPC selling npcSecondsToSell: parseInt( $("#npc-seconds-to-sell").val() ), // Pushers selling arePushersEnabled: $("#enable-pushers-selling").prop("checked"), // Narcos selling enableNarcosSelling: $("#enable-narcos-selling").prop("checked"), enableNPCSell: $("#enable-npc-selling").prop("checked"), } const response = await $.post(`https://${resName}/saveSettings`, JSON.stringify({ clientSettings: clientSettings, serverSettings: serverSettings, sharedSettings: sharedSettings })); showServerResponse(response); }) // Narcos selling function toggleNarcosSelling() { let narcosSelling = $("#enable-narcos-selling").prop("checked"); $("#selling-narcos").find("input, button").not("#enable-narcos-selling").prop("disabled", !narcosSelling); } $("#enable-narcos-selling").change(toggleNarcosSelling); function toggleNarcosBlip() { let narcosBlip = $("#enable-narcos-blip").prop("checked"); $("#narcos-selling-blip-name").prop("disabled", !narcosBlip); $("#narcos-selling-blip-color").prop("disabled", !narcosBlip); $("#narcos-selling-blip-scale").prop("disabled", !narcosBlip); $("#narcos-selling-blip-sprite").prop("disabled", !narcosBlip); } $("#enable-narcos-blip").change(toggleNarcosBlip); function addNarcosSpawnLocation(coords = {}, heading = 0.0) { let newSpawnDiv = $(`
`) newSpawnDiv.find(".max-two-decimals").on("change", maxTwoDecimals); newSpawnDiv.find(".current-coords-btn").click(async function(event) { if(event.shiftKey) { const coordsInUI = { x: parseFloat( newSpawnDiv.find(".coord-x").val() ), y: parseFloat( newSpawnDiv.find(".coord-y").val() ), z: parseFloat( newSpawnDiv.find(".coord-z").val() ) } teleportToCoords(coordsInUI, parseFloat(newSpawnDiv.find(".heading").val())); return; } const data = await getCurrentCoordsAndHeading(); newSpawnDiv.find(".coord-x").val(data.coords.x); newSpawnDiv.find(".coord-y").val(data.coords.y); newSpawnDiv.find(".coord-z").val(data.coords.z); newSpawnDiv.find(".heading").val(data.heading); }); newSpawnDiv.find(".remove-btn").click(function() { newSpawnDiv.remove(); }); $("#narcos-spawn-locations").append(newSpawnDiv); } $("#narcos-add-spawn-btn").click(function() { addNarcosSpawnLocation(); }) function getNarcosBuyerLocations() { let buyerLocations = []; $("#narcos-spawn-locations").find(".spawn-location").each(function() { let spawnDiv = $(this); let coords = { x: parseFloat( spawnDiv.find(".coord-x").val() ), y: parseFloat( spawnDiv.find(".coord-y").val() ), z: parseFloat( spawnDiv.find(".coord-z").val() ) }; let heading = parseFloat( spawnDiv.find(".heading").val() ); buyerLocations.push({ coords: coords, heading: heading }); }) return buyerLocations; } function addNarcosDrug(drugName = "", minQuantity = 1, maxQuantity = 2, minPrice = 500, maxPrice = 1000) { let drugDiv = $(`
`) drugDiv.find(".choose-item-btn").click(async function() { const itemName = await itemsDialog(); drugDiv.find(".drug-name").val(itemName); }).tooltip(); drugDiv.find(".remove-btn").click(function() { drugDiv.remove(); }); $("#narcos-selling-acceptable-drugs").append(drugDiv); } $("#narcos-add-new-drug").click(function() { addNarcosDrug(); }) function getNarcosDrugs() { let drugs = []; $("#narcos-selling-acceptable-drugs").find(".drug").each(function() { let drug = { name: $(this).find(".drug-name").val(), minPrice: parseInt( $(this).find(".drug-min-price").val() ), maxPrice: parseInt( $(this).find(".drug-max-price").val() ), minQuantity: parseInt( $(this).find(".drug-min-quantity").val() ), maxQuantity: parseInt( $(this).find(".drug-max-quantity").val() ) } drugs.push(drug); }) return drugs; } // Pushers function togglePushersSelling() { let enabled = $("#enable-pushers-selling").prop("checked"); $("#selling-pushers").find("input, button").not("#enable-pushers-selling").prop("disabled", !enabled); } $("#enable-pushers-selling").change(togglePushersSelling); function addPusherDrug(pusherDiv, drugData = {}) { let drugDiv = $(`
`); drugDiv.find(".btn-close").click(function() { drugDiv.remove(); }); // Initialize tooltip so player knows what the field is for drugDiv.find(".drug-max-quantity").tooltip(); drugDiv.find(".choose-item-btn").tooltip(); drugDiv.find(".choose-item-btn").click(async function() { const itemName = await itemsDialog(); drugDiv.find(".drug-name").val(itemName); }) pusherDiv.find(".pusher-drugs-list").append(drugDiv); } function addPusher(pusherData = {}) { let pusherDiv = $(`

${ getLocalizedText("menu:pushers:location") }

${ getLocalizedText("menu:pushers:work_time") }

${ getLocalizedText("menu:pushers:work_time:subtitle") } -

${getLocalizedText("menu:invalid_hours")}

${getLocalizedText("menu:invalid_hours")}

${ getLocalizedText("menu:pushers:acceptable_drugs") }


`); pusherDiv.find(".is-always-active").change(function() { let isAlwaysActive = $(this).prop("checked"); pusherDiv.find(".start-hour").prop("disabled", isAlwaysActive); pusherDiv.find(".finish-hour").prop("disabled", isAlwaysActive); if(isAlwaysActive) { pusherDiv.find(".start-hour").val(0); pusherDiv.find(".finish-hour").val(23); } }); pusherDiv.find(".remove-btn").click(function() { pusherDiv.remove(); }); pusherDiv.find(".current-coords-btn").click(async function(event) { if(event.shiftKey) { const coordsInUI = { x: parseFloat( pusherDiv.find(".coord-x").val() ), y: parseFloat( pusherDiv.find(".coord-y").val() ), z: parseFloat( pusherDiv.find(".coord-z").val() ) } teleportToCoords(coordsInUI, parseFloat(pusherDiv.find(".heading").val())); return; } const data = await getCurrentCoordsAndHeading(); pusherDiv.find(".coord-x").val(data.coords.x); pusherDiv.find(".coord-y").val(data.coords.y); pusherDiv.find(".coord-z").val(data.coords.z); pusherDiv.find(".heading").val(data.heading); }); pusherDiv.find(".add-drug").click(function() { addPusherDrug(pusherDiv); }); if (pusherData.coords) { pusherDiv.find(".coord-x").val(pusherData.coords.x); pusherDiv.find(".coord-y").val(pusherData.coords.y); pusherDiv.find(".coord-z").val(pusherData.coords.z); } if(pusherData.heading) { pusherDiv.find(".heading").val(pusherData.heading); } if (pusherData.workTime) { pusherDiv.find(".start-hour").val(pusherData.workTime.startHour); pusherDiv.find(".finish-hour").val(pusherData.workTime.finishHour); const isAlwaysActive = pusherData.workTime.startHour == 0 && pusherData.workTime.finishHour == 23; pusherDiv.find(".is-always-active").prop("checked", isAlwaysActive).change(); } if(pusherData.drugsNeeded) { pusherData.drugsNeeded.forEach(drug => { addPusherDrug(pusherDiv, drug); }); } $.post(`https://${resName}/getServerClock`, {}, function(time) { pusherDiv.find(".server-clock").text(time); }); pusherDiv.find(".pusher-one-drug-only").prop("checked", pusherData.acceptsOnlyOneRandomDrug); $("#pushers-list").append(pusherDiv); return pusherDiv; } $("#add-pusher-btn").click(function() { let pusherDiv = addPusher(); addPusherDrug(pusherDiv); }); function getPusherDrugs(pusherDiv) { let drugs = []; pusherDiv.find(".pusher-drug").each(function() { let drug = { name: $(this).find(".drug-name").val(), minPrice: parseInt( $(this).find(".drug-min-price").val() ), maxPrice: parseInt( $(this).find(".drug-max-price").val() ), maxQuantity: parseInt( $(this).find(".drug-max-quantity").val() ), }; drugs.push(drug); }); return drugs; } function getPushers() { let pushers = {}; let pushersCount = 1; $("#pushers-list").find(".pusher").each(function() { pushers[pushersCount] = { coords: { x: parseFloat( $(this).find(".coord-x").val() ), y: parseFloat( $(this).find(".coord-y").val() ), z: parseFloat( $(this).find(".coord-z").val() ) }, heading: parseFloat( $(this).find(".heading").val() ), workTime: { startHour: parseInt( $(this).find(".start-hour").val() ), finishHour: parseInt( $(this).find(".finish-hour").val() ) }, drugsNeeded: getPusherDrugs($(this)), acceptsOnlyOneRandomDrug: $(this).find(".pusher-one-drug-only").prop("checked"), }; pushersCount++; }) return pushers; } $("#enable-explosion-on-error").change(function() { let enabled = $(this).prop("checked"); $("#seconds-before-explosion").prop("disabled", !enabled); }) // Load settings function loadSettings(fullConfig) { loadModulesSettings(fullConfig.modules); setSelectiveTargetingSettings(fullConfig.selectiveTargeting); // Plane selling $("#enable-plane-selling").prop("checked", fullConfig.enableAirplaneSell); $("#enable-plane-selling").change(); $("#minimum-plane-height").val(fullConfig.heightToSell); $("#time-to-sell-in-plane").val(fullConfig.timeToSellInPlane); $("#enable-plane-police-alert").prop("checked", fullConfig.alarmPoliceInPlane); $("#plane-use-the-whole-ocean").prop("checked", fullConfig.sellUseWholeOcean.plane); $("#plane-use-the-whole-ocean").change(); $("#plane-selling-coords-x").val(fullConfig.sellArea.plane.coords.x); $("#plane-selling-coords-y").val(fullConfig.sellArea.plane.coords.y); $("#plane-selling-coords-z").val(fullConfig.sellArea.plane.coords.z); $("#plane-selling-coords-radius").val(fullConfig.sellArea.plane.radius); fillAcceptableDrugsForDiv("#plane-selling-acceptable-drugs", fullConfig.planeAcceptableDrugs); // Rewards setRewardDivData("#plane-selling-reward-div", fullConfig.rewards.plane); setRewardDivData("#boat-selling-reward-div", fullConfig.rewards.boat); setRewardDivData("#npc-selling-reward-div", fullConfig.rewards.npc); setRewardDivData("#narcos-selling-reward-div", fullConfig.rewards.narcos); setRewardDivData("#pushers-selling-reward-div", fullConfig.rewards.pushers); $("#plane-minimum-police").val(fullConfig.planeSellingMinimumPolice); // Boat selling $("#enable-boat-selling").prop("checked", fullConfig.enableBoatSell); $("#enable-boat-selling").change(); $("#time-to-sell-in-boat").val(fullConfig.timeToSellInBoat); $("#enable-boat-police-alert").prop("checked", fullConfig.alarmPoliceInBoat); $("#boat-use-the-whole-ocean").prop("checked", fullConfig.sellUseWholeOcean.boat); $("#boat-use-the-whole-ocean").change(); $("#boat-selling-coords-x").val(fullConfig.sellArea.boat.coords.x); $("#boat-selling-coords-y").val(fullConfig.sellArea.boat.coords.y); $("#boat-selling-coords-z").val(fullConfig.sellArea.boat.coords.z); $("#boat-selling-coords-radius").val(fullConfig.sellArea.boat.radius); fillAcceptableDrugsForDiv("#boat-selling-acceptable-drugs", fullConfig.boatAcceptableDrugs); $("#boat-minimum-police").val(fullConfig.boatSellingMinimumPolice); // NPC Selling $("#enable-npc-selling").prop("checked", fullConfig.enableNPCSell); $("#enable-npc-selling").change(); $("#npc-selling-min-quantity").val(fullConfig.minNPCSellQuantity); $("#npc-selling-max-quantity").val(fullConfig.maxNPCSellQuantity); $("#npc-accept-chances").val(fullConfig.sellToNPCChancesToAccept); $("#npc-max-drug-quantity").val(fullConfig.maxNPCsSellableDrugQuantity); fillAcceptableDrugsForDiv("#npc-selling-acceptable-drugs", fullConfig.npcAcceptableDrugs); $("#npc-minimum-police").val(fullConfig.npcSellingMinimumPolice); $("#npc-seconds-to-sell").val(fullConfig.npcSecondsToSell); $("#npc-alert-police-chances").val(fullConfig.npcAlertPoliceChances); $("#npc-can-rob-player").prop("checked", fullConfig.canNPCRobPlayer); $("#npc-can-attack-player").prop("checked", fullConfig.canNPCAttackPlayer); // NPC Selling command $("#npc-selling-command-is-enabled").prop("checked", fullConfig.npcSellingCommand.enabled).change(); $("#npc-selling-command").val(fullConfig.npcSellingCommand.command); $("#npc-selling-command-has-to-spawn-npc").prop("checked", fullConfig.npcSellingCommand.hasToSpawnPed); // Narcos selling $("#enable-narcos-selling").prop("checked", fullConfig.enableNarcosSelling); $("#enable-narcos-selling").change(); $("#narcos-model").val(fullConfig.narcosModel), $("#enable-narcos-blip").prop("checked", fullConfig.showNarcosBlip), $("#enable-narcos-blip").change(); $("#narcos-selling-blip-name").val(fullConfig.narcosBlip.name); $("#narcos-selling-blip-color").val(fullConfig.narcosBlip.color); $("#narcos-selling-blip-scale").val(fullConfig.narcosBlip.scale); $("#narcos-selling-blip-sprite").val(fullConfig.narcosBlip.sprite); $("#narcos-location-change").val(fullConfig.narcosLocationChangeTime); $("#narcos-police-alert-chances").val(fullConfig.narcosCallPoliceChances); $("#narcos-accepts-only-one-buyer-per-location").prop("checked", fullConfig.narcosAcceptsOnlyOneBuyerPerLocation); $("#narcos-spawn-locations").empty(); if(fullConfig.narcosBuyerLocations) { fullConfig.narcosBuyerLocations.forEach(location => { addNarcosSpawnLocation(location.coords, location.heading); }); } $("#narcos-selling-acceptable-drugs").empty(); if(fullConfig.narcosNeededDrugs) { fullConfig.narcosNeededDrugs.forEach(drug => { addNarcosDrug(drug.name, drug.minQuantity, drug.maxQuantity, drug.minPrice, drug.maxPrice); }); } $("#narcos-minimum-police").val(fullConfig.narcosSellingMinimumPolice); // Pushers $("#enable-pushers-selling").prop("checked", fullConfig.arePushersEnabled); $("#enable-pushers-selling").change(); $("#pushers-model").val(fullConfig.pusherModel), $("#enable-pushers-blip").prop("checked", fullConfig.showPushersBlips); $("#pushers-selling-blip-name").val(fullConfig.pusherBlip.name); $("#pushers-selling-blip-color").val(fullConfig.pusherBlip.color); $("#pushers-selling-blip-scale").val(fullConfig.pusherBlip.scale); $("#pushers-selling-blip-sprite").val(fullConfig.pusherBlip.sprite); $("#pushers-alert-police-chances").val(fullConfig.pushersCallPoliceChances); $("#pushers-list").empty(); if(fullConfig.pushers) { for(const[pusherId, pusherData] of Object.entries(fullConfig.pushers)) { addPusher(pusherData); } } $("#pushers-minimum-police").val(fullConfig.pushersSellingMinimumPolice); // Pocket craftings $("#pocket-craftings-list").empty(); if(fullConfig.pocketCraftings) { for(const[itemName, itemData] of Object.entries(fullConfig.pocketCraftings)) { addPocketCrafting(itemName, itemData); } } // Effects $("#drugs-effects").empty(); if(fullConfig.drugsEffects) { for(const[itemName, effectData] of Object.entries(fullConfig.drugsEffects)) { addItemEffect(itemName, effectData); } } // Settings setTomSelectValue("#settings_locale", fullConfig.locale) setTomSelectValue("#settings_menuPosition", fullConfig.menuPosition) setTomSelectValue("#settings-targeting-script", fullConfig.targetingScript) $("#enable-fire-on-error").prop("checked", fullConfig.enableFireOnError); $("#enable-explosion-on-error").prop("checked", fullConfig.enableExplosionOnError).change(); $("#seconds-before-explosion").val(fullConfig.secondsBeforeExplosion); $("#enable-discord-logs").prop("checked", fullConfig.areDiscordLogsActive).change() $("#main-discord-webhook").val(fullConfig.mainDiscordWebhook); if(fullConfig.specificWebhooks) { for(const[webhookType, webhookUrl] of Object.entries(fullConfig.specificWebhooks)) { $("#discord-specific-webhooks").find(`[data-webhook-type="${webhookType}"]`).val(webhookUrl); } } // Key to sell to NPCs $("#key-to-sell-to-npcs").val(fullConfig.keyToSellToNPCs); // Minimum police $("#harvestable-items-minimum-police").val(fullConfig.harvestingItemsMinimumPolice); $("#laboratory-minimum-police").val(fullConfig.useLaboratoryMinimumPolice); $("#fields-minimum-police").val(fullConfig.harvestFieldMinimumPolice); // Automatic farm $("#allow-afk-farming-for-harvest").prop("checked", fullConfig.allowAfkFarmingForHarvest); $("#allow-afk-farming-for-laboratories").prop("checked", fullConfig.allowAfkFarmingForLaboratories); // Price reduction $("#minimum-cops-for-base-price").val(fullConfig.priceReduction.minimumPolice); $("#price-reduction-percentage").val(fullConfig.priceReduction.reductionPercentage); $("#price-reduction-interval").val(fullConfig.priceReduction.reductionInterval); // Auctions $("#auction-check-interval").val(fullConfig.auctions.nextAuctionEachMinutes); } // Settings function getSpecificWebhooks() { let webhooks = {}; $("#discord-specific-webhooks").find(".webhook").each(function() { let webhookType = $(this).data("webhookType"); let webhook = $(this).val(); if(webhook) { webhooks[webhookType] = webhook; } }) return webhooks; } function toggleSelectiveTargeting() { const enabled = $("#settings-targeting-script").val() != "none"; $("#selective-targeting-container").find(".form-check-input").prop("disabled", !enabled); } function getSelectiveTargetingSettings() { let selectiveTargeting = {}; $("#selective-targeting-container").find(".form-check-input").each(function(index, element) { element = $(element); let featureName = element.data("featureName"); let enabled = element.prop("checked"); selectiveTargeting[featureName] = enabled; }); return selectiveTargeting; } function setSelectiveTargetingSettings(selectiveTargeting) { $("#selective-targeting-container").find(".form-check-input").each(function(index, element) { element = $(element); let featureName = element.data("featureName"); let enabled = selectiveTargeting[featureName]; element.prop("checked", enabled); }); toggleSelectiveTargeting(); } $("#settings-targeting-script").change(function() { toggleSelectiveTargeting(); }) $("#settings").submit(async function(event) { if(isThereAnyErrorInForm(event)) return; let clientSettings = { secondsBeforeExplosion: parseInt( $("#seconds-before-explosion").val() ), menuPosition: $("#settings_menuPosition").val(), // Key to sell to NPCs keyToSellToNPCs: parseInt( $("#key-to-sell-to-npcs").val() ), // Targeting targetingScript: $("#settings-targeting-script").val(), selectiveTargeting: getSelectiveTargetingSettings() } let sharedSettings = { locale: $("#settings_locale").val(), // NPC selling command npcSellingCommand: { enabled: $("#npc-selling-command-is-enabled").prop("checked"), command: $("#npc-selling-command").val(), hasToSpawnPed: $("#npc-selling-command-has-to-spawn-npc").prop("checked") }, modules: getModulesSettings(), } let serverSettings = { enableFireOnError: $("#enable-fire-on-error").prop("checked"), enableExplosionOnError: $("#enable-explosion-on-error").prop("checked"), areDiscordLogsActive: $("#enable-discord-logs").prop("checked"), mainDiscordWebhook: $("#main-discord-webhook").val(), specificWebhooks: getSpecificWebhooks(), harvestingItemsMinimumPolice: parseInt( $("#harvestable-items-minimum-police").val() ), useLaboratoryMinimumPolice: parseInt( $("#laboratory-minimum-police").val() ), harvestFieldMinimumPolice: parseInt( $("#fields-minimum-police").val() ), allowAfkFarmingForHarvest: $("#allow-afk-farming-for-harvest").prop("checked"), allowAfkFarmingForLaboratories: $("#allow-afk-farming-for-laboratories").prop("checked"), priceReduction: { minimumPolice: parseInt( $("#minimum-cops-for-base-price").val()), reductionPercentage: parseInt( $("#price-reduction-percentage").val()), reductionInterval: parseInt( $("#price-reduction-interval").val()) }, auctions: { nextAuctionEachMinutes: parseInt( $("#auction-check-interval").val() ), } } const response = await $.post(`https://${resName}/saveSettings`, JSON.stringify({ clientSettings: clientSettings, serverSettings: serverSettings, sharedSettings: sharedSettings })); showServerResponse(response); refreshTranslations(sharedSettings.locale); }) $("#enable-discord-logs").change(function() { let enabled = $(this).prop("checked"); $("#main-discord-webhook").prop("disabled", !enabled); $("#main-discord-webhook").prop("required", enabled); $("#discord-specific-webhooks").find(".webhook").each(function() { $(this).prop("disabled", !enabled); }); }) // Restore to default config $(".restore-to-default-config").click(async function() { if(!await confirmDeletion( getLocalizedText("menu:are_you_sure_to_restore_settings") )) return; const defaultConfig = await $.post(`https://${resName}/getDefaultConfiguration`); loadSettings(defaultConfig) }) // Drugs effects async function getItemLabel(itemName) { return new Promise(resolve => { $.post(`https://${resName}/getItemLabel`, JSON.stringify({itemName: itemName}), function(itemLabel) { resolve(itemLabel); }); }) } async function addItemEffect(itemName, itemData={}, isNew = false) { let itemLabel = await getItemLabel(itemName); let itemEffectDiv = $(`

${itemLabel} (${itemName})

${ getLocalizedText("menu:effects:taking_method") }

${ getLocalizedText("menu:effects:drunk_effects") }

${ getLocalizedText("menu:effects:visual_color_effects") }

${ getLocalizedText("menu:effects:perks") }

${ getLocalizedText("menu:effects:cumulative_effect") }

${ getLocalizedText("menu:effects:special_effect") }


`); if(itemData.takingMethod) { itemEffectDiv.find(`input[name=drug-assume-type-${itemName}][value=${itemData.takingMethod}]`).prop("checked", true); } if(itemData.effectsDuration) { itemEffectDiv.find(".effect-duration").val(itemData.effectsDuration); } if(itemData.effects) { for(let effect of itemData.effects) { itemEffectDiv.find(`input[value=${effect}]`).prop("checked", true); } } if(itemData.cumulativeEffects) { for(let cumulativeEffect of itemData.cumulativeEffects) { itemEffectDiv.find(`.cumulative-effect[data-cumulative-name=${cumulativeEffect.type}]`).find(".cumulative-effect-checkbox").prop("checked", true); itemEffectDiv.find(`input[name=drug-cumulative-${cumulativeEffect.type}-${itemName}][value=${cumulativeEffect.action}]`).prop("checked", true); itemEffectDiv.find(`.cumulative-effect[data-cumulative-name=${cumulativeEffect.type}]`).find(".cumulative-effect-amount").val(cumulativeEffect.amount); } } if(isNew) { itemEffectDiv.find(".title").append(` - ${ getLocalizedText("menu:effects:may_need_restart") }`) } itemEffectDiv.data("itemName", itemName); itemEffectDiv.find(".remove-effect-btn").click(function() { itemEffectDiv.remove(); }) $("#drugs-effects").append(itemEffectDiv); } function getEffectsDataFromDiv(effectDiv, itemName) { let effectData = { takingMethod: $(`input[name=drug-assume-type-${itemName}]:checked`).val(), effects: [], effectsDuration: parseInt( effectDiv.find(".effect-duration").val() ), cumulativeEffects: [] }; let visualColorEffect = $(`input[name=camera-color-effects-${itemName}]:checked`).val(); if(visualColorEffect != "none") { effectData.effects.push(visualColorEffect) } const specialEffect = $(`input[name=drug-special-effect-${itemName}]:checked`).val(); if(specialEffect != "none") { effectData.effects.push(specialEffect) } effectDiv.find(".cumulative-effect").each(function() { if (!$(this).find(".cumulative-effect-checkbox").prop("checked")) return; const type = $(this).data("cumulativeName"); const action = $(this).find("input[type=radio]:checked").val() || "increase"; // In case people don't select any const amount = parseInt( $(this).find(".cumulative-effect-amount").val() ); effectData.cumulativeEffects.push({type, action, amount}); }); effectDiv.find(".stackable-effect:checked").each(function() { effectData.effects.push( $(this).val() ); }); return effectData; } function getAllEffectsData() { let effectsData = {}; $("#drugs-effects").find(".drug-effect").each(function() { let itemName = $(this).data("itemName"); effectsData[itemName] = getEffectsDataFromDiv($(this), itemName); }); return effectsData; } $("#create-new-item-effect-btn").click(async function() { const itemName = await itemsDialog(); addItemEffect(itemName, {}, true); }); // Saves the new effects $("#effects").submit(async function(event) { if(isThereAnyErrorInForm(event)) return; let serverSettings = { drugsEffects: getAllEffectsData(), } let clientSettings = {} let sharedSettings = {} const response = await $.post(`https://${resName}/saveSettings`, JSON.stringify({ clientSettings: clientSettings, serverSettings: serverSettings, sharedSettings: sharedSettings })); showServerResponse(response); }); /* AUCTIONS */ let auctionsDatatable = $("#auctions-container").DataTable( { "lengthMenu": [10, 15, 20], "columnDefs": [ { "targets": -1, // Ultima colonna "data": null, "className": "col-1", "defaultContent": `
` } ], "createdRow": function ( row, data, index ) { $(row).addClass("clickable"); $(row).click(function() { let auctionId = parseInt(data[0]); editAuction(auctionId); }); $(row).find(".force-start-auction-btn").click(async function(event) { event.stopPropagation(); const auctionId = parseInt(data[0]); $.post(`https://${resName}/forceStartAuction`, JSON.stringify({auctionId})); }).tooltip().prop("title", getLocalizedText("menu:start_now")); }, } ); let auctions = {}; async function loadAuctions() { const rawAuctions = await $.post(`https://${resName}/getAllAuctions`); // Manually create the table to avoid incompatibilities due table indexing auctions = {}; for(const[k, auction] of Object.entries(rawAuctions)) { auctions[auction.id] = auction; } auctionsDatatable.clear(); for(const[auctionId, auction] of Object.entries(auctions)) { auctionsDatatable.row.add([ auctionId || "???", auction.label || "???", ]) } auctionsDatatable.draw() } function setAuctionConfig(auction) { const config = auction ? auction.config : {}; $("#auction-label").val(auction?.label || "Default"); $("#auction-min-players-online").val(config.minPlayersForAuction ?? 3); $("#auction-min-police-online").val(config.minPoliceOnline ?? 0); $("#auction-randomize-items").prop("checked", config.randomizeItems ?? false); $("#auction-multiplier").val(config.multiplier ?? 1); $("#auction-max-rounds").val(config.maxRounds ?? 3); $("#auction-alert-police-after-round").val(config.alertPoliceAfterRound ?? 2); $("#auction-time-between-rounds").val(config.timeBetweenRoundsSeconds ?? 30); $("#auction-warning-before-start").val(config.warningBeforeAuctionStartMinutes ?? 15); $("#auction-no-bid-timeout").val(config.noBidTimeoutSeconds ?? 30); $("#auction-min-bid-increment").val(config.minBidIncrement ?? 100); $("#auction-blip-btn").data("blipData", config.blipData ?? getDefaultBlipCustomization()); if(config.accountToPayWith) { setRewardDivData("#auction-account-to-pay-with", config.accountToPayWith); } // Locations $("#auction-locations-list").empty(); if(config.locations) { config.locations.forEach(location => { addAuctionLocation(location); }); } // Items $("#auction-items-list").empty(); if(config.objectsRewards) { config.objectsRewards.forEach(item => { addAuctionItem(item); }); } } $("#new-auction-btn").click(function() { let auctionModal = $("#auction-modal"); auctionModal.modal("show"); auctionModal.data("action", "create"); setAuctionConfig(); // Adapts the modal from edit mode to create mode $("#delete-auction-btn").hide(); $("#auction-modal-confirm-btn").text( getLocalizedText("menu:create") ); }) function editAuction(auctionId) { let auction = auctions[auctionId]; let auctionModal = $("#auction-modal"); auctionModal.modal("show"); auctionModal.data("action", "edit"); auctionModal.data("auctionId", auctionId); setAuctionConfig(auction); // Adapts the modal from create mode to edit mode $("#delete-auction-btn").show(); $("#auction-modal-confirm-btn").text( getLocalizedText("menu:save") ); } function getAuctionSetup() { return { label: $("#auction-label").val(), config: { minPlayersForAuction: parseInt( $("#auction-min-players-online").val() ), minPoliceOnline: parseInt( $("#auction-min-police-online").val() ), blipData: $("#auction-blip-btn").data("blipData"), randomizeItems: $("#auction-randomize-items").prop("checked"), multiplier: parseFloat( $("#auction-multiplier").val() ), maxRounds: parseInt( $("#auction-max-rounds").val() ), alertPoliceAfterRound: parseInt( $("#auction-alert-police-after-round").val() ), accountToPayWith: getRewardDivData("#auction-account-to-pay-with"), timeBetweenRoundsSeconds: parseInt( $("#auction-time-between-rounds").val() ), warningBeforeAuctionStartMinutes: parseInt( $("#auction-warning-before-start").val() ), noBidTimeoutSeconds: parseInt( $("#auction-no-bid-timeout").val() ), minBidIncrement: parseInt( $("#auction-min-bid-increment").val() ), objectsRewards: getAuctionItems(), locations: getAuctionLocations() } } } $("#auction-form").submit(async function(event) { if(isThereAnyErrorInForm(event)) return; let auction = getAuctionSetup(); let modal = $("#auction-modal"); let action = $(modal).data("action"); let response = null; switch(action) { case "create": { response = await $.post(`https://${resName}/createNewAuction`, JSON.stringify(auction)); break; } case "edit": { let auctionId = modal.data("auctionId"); response = await $.post(`https://${resName}/updateAuction`, JSON.stringify({ auctionId, auction })); break; } } modal.modal("hide"); loadAuctions(); showServerResponse(response); }); $("#delete-auction-btn").click(async function() { if(!await confirmDeletion()) return; let auctionId = $("#auction-modal").data("auctionId"); const response = await $.post(`https://${resName}/deleteAuction`, JSON.stringify({auctionId})); $("#auction-modal").modal("hide"); loadAuctions(); showServerResponse(response); }) function addAuctionLocation(location = {}) { const div = $(`
${getLocalizedText("menu:broker_ped")}
${getLocalizedText("menu:broker_vehicle")}
${getLocalizedText("menu:text")}

`); div.find(".remove-location-btn").click(function() { div.remove(); }); // Broker div.find(".broker-model").val(location.broker?.model || "s_m_m_highsec_01"); div.find(".broker-coordinates-x").val(location.broker?.coordinates?.x || ""); div.find(".broker-coordinates-y").val(location.broker?.coordinates?.y || ""); div.find(".broker-coordinates-z").val(location.broker?.coordinates?.z || ""); div.find(".broker-heading").val(location.broker?.heading || ""); div.find(".choose-broker-coordinates-btn").click(async function() { const model = div.find(".broker-model").val(); const data = await placeEntity(model, "ped"); if(!data) return; div.find(".broker-coordinates-x").val(data.coords.x); div.find(".broker-coordinates-y").val(data.coords.y); div.find(".broker-coordinates-z").val(data.coords.z); div.find(".broker-heading").val(data.heading); }); // Broker vehicle div.find(".vehicle-model").val(location.vehicle?.model || "burrito3"); div.find(".vehicle-coordinates-x").val(location.vehicle?.coordinates?.x || ""); div.find(".vehicle-coordinates-y").val(location.vehicle?.coordinates?.y || ""); div.find(".vehicle-coordinates-z").val(location.vehicle?.coordinates?.z || ""); div.find(".vehicle-heading").val(location.vehicle?.heading || ""); div.find(".choose-vehicle-coordinates-btn").click(async function() { const model = div.find(".vehicle-model").val(); const data = await placeEntity(model, "vehicle"); if(!data) return; div.find(".vehicle-coordinates-x").val(data.coords.x); div.find(".vehicle-coordinates-y").val(data.coords.y); div.find(".vehicle-coordinates-z").val(data.coords.z); div.find(".vehicle-heading").val(data.heading); }); // Text div.find(".text-coordinates-x").val(location.text?.coordinates?.x || ""); div.find(".text-coordinates-y").val(location.text?.coordinates?.y || ""); div.find(".text-coordinates-z").val(location.text?.coordinates?.z || ""); div.find(".choose-text-coordinates-btn").click(async function() { const data = await placeEntity(); if(!data) return; div.find(".text-coordinates-x").val(data.x); div.find(".text-coordinates-y").val(data.y); div.find(".text-coordinates-z").val(data.z); }); $("#auction-locations-list").append(div); } $("#add-auction-location-btn").click(function() { addAuctionLocation(); }) function getAuctionLocations() { let locations = []; $("#auction-locations-list").find(".auction-location").each(function() { let location = { broker: { model: $(this).find(".broker-model").val(), coordinates: { x: parseFloat( $(this).find(".broker-coordinates-x").val() ), y: parseFloat( $(this).find(".broker-coordinates-y").val() ), z: parseFloat( $(this).find(".broker-coordinates-z").val() ), }, heading: parseFloat( $(this).find(".broker-heading").val() ), }, vehicle: { model: $(this).find(".vehicle-model").val(), coordinates: { x: parseFloat( $(this).find(".vehicle-coordinates-x").val() ), y: parseFloat( $(this).find(".vehicle-coordinates-y").val() ), z: parseFloat( $(this).find(".vehicle-coordinates-z").val() ), }, heading: parseFloat( $(this).find(".vehicle-heading").val() ), }, text: { coordinates: { x: parseFloat( $(this).find(".text-coordinates-x").val() ), y: parseFloat( $(this).find(".text-coordinates-y").val() ), z: parseFloat( $(this).find(".text-coordinates-z").val() ), } } } locations.push(location); }); return locations; } function addAuctionItem(item={}) { const div = $(`
`); const objectDiv = createDivForObjectChoose(item); div.find(".btn-close").after(objectDiv); div.find(".btn-close").click(function() { div.remove(); }); div.find("[data-bs-toggle=tooltip]").tooltip(); div.find(".item-quantity").val(item.quantity || 10); div.find(".item-base-price").val(item.basePrice || 1000); setChoosenObject(objectDiv, item); $("#auction-items-list").append(div); } $("#add-auction-item-btn").click(function() { addAuctionItem(); }); function getAuctionItems() { let items = []; $("#auction-items-list").find(".auction-item").each(function() { const object = getChoosenObject($(this)); let item = { quantity: parseInt( $(this).find(".item-quantity").val() ), basePrice: parseInt( $(this).find(".item-base-price").val() ), name: object.name, label: object.label, type: object.type, } items.push(item); }); return items; } $("#auction-blip-btn").click(async function() { const oldBlipData = $(this).data("blipData"); const blipData = await blipDialog(oldBlipData); $(this).data("blipData", blipData); }); // [[ NEXUS ]] const voteInstanceRater = raterJs({ starSize: 35, element: document.querySelector("#vote-instance-rater"), rateCallback: async function rateCallback(rating, done) { const instanceId = $("#nexus-modal").data("instance").id; const success = await $.post(`https://${resName}/nexus/rateInstance`, JSON.stringify({rating, instanceId})); if(success) voteInstanceRater.setRating(rating); done(); } }); const averageInstanceVotes = raterJs({ starSize: 20, readOnly: true, element: document.querySelector("#nexus-modal-instance-average-rating"), }); $("#nexus-import-instance-btn").click(async function() { const instance = $("#nexus-modal").data("instance"); const id = instance.id; const mappedItemsNames = await itemsMapperDialog(instance.requiredItemsNames); if(!mappedItemsNames) return; const response = await $.post(`https://${resName}/nexus/importInstance`, JSON.stringify({id, mappedItemsNames})); $("#nexus-modal").modal("hide"); if(response === true) reloadAllData(); showServerResponse(response); }); let nexusDataTable = $("#nexus-table").DataTable({ "lengthMenu": [5, 10, 15, 20], "pageLength": 10, "order": [[4, 'desc'], [5, 'desc']], "createdRow": function (row, data, index) { $(row).addClass("clickable"); $(row).click(function () { const instance = $(this).data("instance"); showInstance(instance); $("#nexus-modal").modal("show"); }); }, "columnDefs": [{ "defaultContent": "???", "targets": "_all" }] }); function showInstance(instance) { $("#nexus-modal").data("instance", instance); $("#nexus-modal-instance-listing-label").text(instance.label); $("#nexus-instance-content-type").text(instance.type); $("#nexus-instance-content-amount").text(instance.content.length); $("#nexus-modal-instance-description").text(instance.description || getLocalizedText("menu:nexus:no_description")); $("#nexus-modal-instance-author").text(instance.author); // Content names and labels $("#nexus-modal-instance-content").empty(); instance.content.forEach(content => { $("#nexus-modal-instance-content").append(`
  • ${content.label || content.name}
  • `); }); // Votes if(instance?.votes?.total > 0) { averageInstanceVotes.setRating(instance?.votes.averageRating); } else { averageInstanceVotes.setRating(0); } $("#nexus-modal-instance-total-votes").text(instance.votes?.total || 0); // This server vote voteInstanceRater.setRating(0); } $("#upload-to-nexus-btn").click(async function() { const type = await listDialog(getLocalizedText("menu:nexus:data_to_share"), getLocalizedText("menu:search"), [ {value: "harvestable_item", label: getLocalizedText("menu:harvestable_item")}, {value: "drug_field", label: getLocalizedText("menu:drug_field")}, {value: "crafting_recipe", label: getLocalizedText("menu:crafting_recipe")}, {value: "laboratory", label: getLocalizedText("menu:laboratory")}, ]); if(!type) return; let dataToChooseFrom = []; // Depending on the type, we retrieve the possible data and create a multiSelectDialog switch(type) { case "harvestable_item": dataToChooseFrom = await $.post(`https://${resName}/getAllHarvestableItems`); break; case "drug_field": dataToChooseFrom = await $.post(`https://${resName}/getAllDrugsFields`); break; case "crafting_recipe": dataToChooseFrom = await $.post(`https://${resName}/getAllCraftingRecipes`); break; case "laboratory": dataToChooseFrom = await $.post(`https://${resName}/getAllLaboratories`); break; } if(!dataToChooseFrom) return; let elements = []; Object.values(dataToChooseFrom).forEach(data => { elements.push({ value: data.id, label: data.id + " - " + (data.label || data.name) }); }) const selectedData = await multiSelectDialog(getLocalizedText("menu:nexus:data_to_share"), getLocalizedText("menu:search"), elements); if(!selectedData) return; $("#nexus-modal-upload").data("selectedData", selectedData); $("#nexus-modal-upload").data("dataType", type); $("#nexus-upload-label").val(""); $("#nexus-upload-description").val(""); $("#nexus-upload-accept-tos").prop("checked", false); $("#nexus-modal-upload").modal("show"); }); $("#nexus-upload-form").submit(async function(event) { if(isThereAnyErrorInForm(event)) return; const dataToUpload = { type: $("#nexus-modal-upload").data("dataType"), ids: $("#nexus-modal-upload").data("selectedData"), label: $("#nexus-upload-label").val(), description: $("#nexus-upload-description").val(), } const result = await $.post(`https://${resName}/nexus/uploadData`, 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 sharedData = await $.get(`https://${resName}/nexus/getSharedData`); if(!sharedData) { swal("Error", getLocalizedText("menu:nexus:not_available"), "error"); resetNexus(); return; } nexusDataTable.clear() Object.values(sharedData).forEach(instance => { const roundedAverageRating = instance?.votes?.averageRating ? Math.round(instance.votes.averageRating) : 0; const ratingStars = instance?.votes?.total ? "⭐".repeat(roundedAverageRating) : getLocalizedText("menu:nexus:not_rated"); const limitedDescription = instance.description?.length > 30 ? instance.description.substring(0, 30) + "..." : instance.description; const amount = instance.content.length; const rawRow = nexusDataTable.row.add( [instance.label, limitedDescription, instance.type, amount, ratingStars, instance.votes?.total || 0, instance.author] ); const rowDiv = $(rawRow.node()); $(rowDiv).data("instance", instance); }) 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(); } function reloadAllData() { resetNexus(); loadHarvestableItems(); loadDrugsFields(); loadCraftingRecipes(); loadLaboratories(); loadAuctions(); } // Open/Close menu function openMenu(version, fullConfig) { $("#advanced-drugs-creator-version").text(version); $("#drugs_creator").show(); reloadAllData(); window.dispatchEvent(new Event('menuOpened')); loadSettings(fullConfig); } function closeMenu() { $("#drugs_creator").hide(); $.post(`https://${resName}/close`, {}) } $("#close-main-btn").click(closeMenu); function playSound(name, speed = 1.0, volume = 1.0) { // Create an AudioContext var audioCtx = new (window.AudioContext || window.webkitAudioContext)(); // Create the audio element var audio = new Audio(`./assets/audio/${name}.mp3`); audio.playbackRate = speed; // Create a media element source var source = audioCtx.createMediaElementSource(audio); // Create a gain node var gainNode = audioCtx.createGain(); gainNode.gain.value = volume; // Set the volume // Connect the source to the gain node and the gain node to the destination source.connect(gainNode); gainNode.connect(audioCtx.destination); // Play the audio audio.play(); } // Messages received by client window.addEventListener('message', (event) => { let data = event.data; let action = data.action; if (action == 'openMenu') { openMenu(data.version, data.fullConfig); } else if (action == "playSound") { playSound(data.name, data.speed, data.volume); } })