// ==UserScript==
// @name Jari's Quick Assign Narcos Script
// @namespace http://tampermonkey.net/
// @version 1.0
// @description Settings tab & quickly assigns Narcos to a selected production. Reloads when you press ''OK''
// @author Jari [409], Baccy [12578]
// @match https://cartelempire.online/settings
// @match https://cartelempire.online/Production*
// @icon https://i.ibb.co/67cBgvHQ/QNA.png
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_addStyle
// ==/UserScript==
(function() {
'use strict';
// --- Configuration ---
const SETTINGS_KEY_ENABLED = 'jari_script_enabled';
const SETTINGS_KEY_TARGET = 'jari_auto_allocate_target';
const PRODUCTION_TARGETS = { /* IDs from v1.7 */
"Street Crimes": "6", "Doctors Office": "5", "Weed Field": "2",
"Alcohol Still": "1", "Cocaine Factory": "3"
};
const PRODUCTION_TARGET_NAMES = Object.keys(PRODUCTION_TARGETS);
// !! CRITICAL !! DOUBLE-CHECK THIS SELECTOR !!
// This MUST point *ONLY* to the element displaying the number of *IDLE* narcos.
// Use Developer Tools (F12 -> Inspector) on the Production page.
// If this points to the wrong number (e.g., Total Narcos, or Street Crimes count),
// the script WILL assign the wrong amount!
const IDLE_NARCO_SELECTOR = '.idleNarcos'; // <--- *** VERIFY THIS SELECTOR IS CORRECT!!! ***
// --- CSS ---
GM_addStyle(`
/* Styles copied from v1.8 */
.jari-switch-label { position: relative; display: inline-block; width: 40px; height: 22px; vertical-align: middle; margin-left: 5px; }
.jari-switch-input { opacity: 0; width: 0; height: 0; }
.jari-slider { position: absolute; cursor: pointer; top: 0; left: 0; right: 0; bottom: 0; background-color: #212529; border: 1px solid #495057; transition: .4s; border-radius: 22px; }
.jari-slider:before { position: absolute; content: ""; height: 16px; width: 16px; left: 2px; bottom: 2px; background-color: #595C5F; transition: .4s; border-radius: 50%; }
.jari-switch-input:checked + .jari-slider { background-color: #0D6EFD; border-color: #0D6EFD; }
.jari-switch-input:checked + .jari-slider:before { background-color: #FFFFFF; transform: translateX(18px); }
.jari-setting-row { display: flex; align-items: center; margin-bottom: 15px; }
.jari-confirm-overlay-v17 { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(0, 0, 0, 0.7); display: flex; justify-content: center; align-items: center; z-index: 10000; }
.jari-confirm-box-v17 { background-color: #212529; color: #dee2e6; padding: 20px 25px; border-radius: 6px; border: 1px solid #444; box-shadow: 0 8px 25px rgba(0, 0, 0, 0.5); min-width: 300px; max-width: 450px; z-index: 10001; overflow: hidden; }
.jari-confirm-box-v17 p { margin-top: 0; margin-bottom: 25px; font-size: 1rem; line-height: 1.6; text-align: left; color: #fff; }
.jari-confirm-buttons-v17 { text-align: right; margin-top: 15px; }
.jari-confirm-buttons-v17 button { color: white; border: none; padding: 8px 18px; border-radius: 5px; cursor: pointer; font-size: 0.95em; font-weight: 500; margin-left: 10px; transition: background-color 0.2s ease, box-shadow 0.2s ease; }
.jari-confirm-ok-v17 { background-color: #0d6efd; box-shadow: 0 2px 5px rgba(13, 110, 253, 0.3); }
.jari-confirm-cancel-v17 { background-color: #dc3545; box-shadow: 0 2px 5px rgba(220, 53, 69, 0.3); }
.jari-confirm-buttons-v17 button:hover { filter: brightness(110%); box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3); }
`);
// --- Helper Functions ---
function getSetting(key, defaultValue) { return GM_getValue(key, defaultValue); }
function setSetting(key, value) { GM_setValue(key, value); }
// --- Settings Page Logic (Identical to v1.8) ---
function setupSettingsPage() {
console.log("Jari's Settings Script v1.9 (Fixes & Debug): Initializing on /settings page...");
// ... (Settings UI setup code is exactly the same as v1.8) ...
const settingsContentSelector = '.tab-content'; const settingsNavSelector = '.nav-tabs'; const settingsContent = document.querySelector(settingsContentSelector); const settingsNav = document.querySelector(settingsNavSelector); if (!settingsContent || !settingsNav) { console.error("Jari's Script: Could not find settings containers."); return; } if (document.querySelector('a[href="#jaris-userscripts-content"]')) { console.log("Jari's Script: Settings tab already exists."); return; } const newTab = document.createElement('li'); newTab.className = 'nav-item'; newTab.innerHTML = `<a class="nav-link" data-bs-toggle="tab" href="#jaris-userscripts-content">Jari's Userscripts</a>`; settingsNav.appendChild(newTab); const newPane = document.createElement('div'); newPane.className = 'tab-pane fade'; newPane.id = 'jaris-userscripts-content'; newPane.style.padding = '15px'; const toggleDiv = document.createElement('div'); toggleDiv.className = 'jari-setting-row'; const toggleLabel = document.createElement('label'); toggleLabel.htmlFor = 'jari-script-enable-checkbox'; toggleLabel.textContent = 'Enable Quick Narco Assignment:'; toggleLabel.style.marginRight = '10px'; toggleLabel.style.fontWeight = 'bold'; const switchLabel = document.createElement('label'); switchLabel.className = 'jari-switch-label'; switchLabel.innerHTML = `<input type="checkbox" id="jari-script-enable-checkbox" class="jari-switch-input"><span class="jari-slider"></span>`; toggleDiv.appendChild(toggleLabel); toggleDiv.appendChild(switchLabel); newPane.appendChild(toggleDiv); const dropdownDiv = document.createElement('div'); dropdownDiv.className = 'jari-setting-row'; const label = document.createElement('label'); label.htmlFor = 'jari-auto-allocate-select'; label.textContent = 'Select Quick Allocation Target:'; label.className = 'form-label'; label.style.fontWeight = 'bold'; label.style.marginRight = '10px'; const select = document.createElement('select'); select.id = 'jari-auto-allocate-select'; select.className = 'form-select'; select.style.maxWidth = '250px'; PRODUCTION_TARGET_NAMES.forEach(target => { const option = document.createElement('option'); option.value = target; option.textContent = target; select.appendChild(option); }); dropdownDiv.appendChild(label); dropdownDiv.appendChild(select); newPane.appendChild(dropdownDiv); const saveButtonDiv = document.createElement('div'); saveButtonDiv.style.marginTop = '20px'; const saveButton = document.createElement('button'); saveButton.id = 'jari-save-settings'; saveButton.textContent = 'Save Settings'; saveButton.className = 'btn btn-primary'; saveButtonDiv.appendChild(saveButton); newPane.appendChild(saveButtonDiv); settingsContent.appendChild(newPane); console.log("Jari's Script: Settings tab and content added."); const savedEnabled = getSetting(SETTINGS_KEY_ENABLED, false); const savedTarget = getSetting(SETTINGS_KEY_TARGET, PRODUCTION_TARGET_NAMES[0]); const enableCheckbox = document.getElementById('jari-script-enable-checkbox'); const targetSelect = document.getElementById('jari-auto-allocate-select'); if (enableCheckbox) enableCheckbox.checked = savedEnabled; if (targetSelect) targetSelect.value = savedTarget; console.log("Jari's Script: Loaded settings.", { enabled: savedEnabled, target: savedTarget }); saveButton.addEventListener('click', () => { const currentEnabled = enableCheckbox ? enableCheckbox.checked : false; const currentTarget = targetSelect ? targetSelect.value : PRODUCTION_TARGET_NAMES[0]; setSetting(SETTINGS_KEY_ENABLED, currentEnabled); setSetting(SETTINGS_KEY_TARGET, currentTarget); saveButton.textContent = 'Saved!'; saveButton.classList.remove('btn-primary'); saveButton.classList.add('btn-success'); setTimeout(() => { saveButton.textContent = 'Save Settings'; saveButton.classList.remove('btn-success'); saveButton.classList.add('btn-primary'); }, 1500); console.log("Jari's Script: Settings saved.", { enabled: currentEnabled, target: currentTarget }); });
} // End of setupSettingsPage
// --- Custom Confirmation Box Function (v1.7 logic) ---
function showStyledConfirm(message, yesCallback, noCallback) { /* Identical to v1.8 */
const existingDialog = document.getElementById('jari-confirm-dialog-v17'); if (existingDialog) { existingDialog.remove(); } const overlay = document.createElement('div'); overlay.id = 'jari-confirm-dialog-v17'; overlay.className = 'jari-confirm-overlay-v17'; const box = document.createElement('div'); box.className = 'jari-confirm-box-v17'; const p = document.createElement('p'); p.textContent = message; const buttonDiv = document.createElement('div'); buttonDiv.className = 'jari-confirm-buttons-v17'; const cancelButton = document.createElement('button'); cancelButton.textContent = 'Cancel'; cancelButton.className = 'jari-confirm-cancel-v17'; cancelButton.onclick = () => { overlay.remove(); if (noCallback) noCallback(); }; const okButton = document.createElement('button'); okButton.textContent = 'OK'; okButton.className = 'jari-confirm-ok-v17'; okButton.onclick = () => { overlay.remove(); if (yesCallback) yesCallback(); }; buttonDiv.appendChild(cancelButton); buttonDiv.appendChild(okButton); box.appendChild(p); box.appendChild(buttonDiv); overlay.appendChild(box); document.body.appendChild(overlay);
}
// --- Production Page Logic ---
function getIdleNarcoCount() {
const element = document.querySelector(IDLE_NARCO_SELECTOR);
if (!element) {
console.error("AutoAssign DEBUG: Idle narco element NOT FOUND using selector:", IDLE_NARCO_SELECTOR);
alert("AutoAssign Error: Idle narco element not found. Please check the script's IDLE_NARCO_SELECTOR configuration.");
return null;
}
const countText = element.textContent.trim();
// DEBUG: Log the raw text found
console.log("AutoAssign DEBUG: Raw text found for idle count:", countText);
const count = parseInt(countText.replace(/,/g, ''), 10); // Remove commas before parsing
if (isNaN(count)) {
console.error("AutoAssign DEBUG: FAILED to parse idle narco count from text:", countText);
alert("AutoAssign Error: Cannot parse idle narco count from page element.");
return null;
}
// DEBUG: Log the parsed count
console.log("AutoAssign DEBUG: Parsed idle narco count as:", count);
return count;
}
// MODIFIED: Added window.location.reload() on success
function assignNarcos(targetId, targetName, amount) {
const url = `/Production/Assign/${targetId}`;
const postData = `toAssign=${encodeURIComponent(amount)}`;
// DEBUG: Log exactly what is being sent
console.log(`AutoAssign DEBUG: Sending POST to ${url} with body: ${postData}`);
fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: postData })
.then(response => { if (!response.ok) { throw new Error(`HTTP error! status: ${response.status} ${response.statusText}`); } return response.json(); })
.then(data => {
console.log(`AutoAssign (Fetch): Assignment successful for ${targetName}. Resp:`, data);
// RELOAD PAGE on success
window.location.reload();
})
.catch(error => {
console.error(`AutoAssign (Fetch): Assignment failed for ${targetName}. Error:`, error);
alert(`AutoAssign Error: Failed to assign narcos to ${targetName}. ${error.message}. Check console.`);
});
}
// MODIFIED: Added extra debug logs
function runAutoAssignLogic() {
console.log("AutoAssign (Styled Confirm / Debug): Running on /Production page.");
const isEnabled = getSetting(SETTINGS_KEY_ENABLED, false);
if (!isEnabled) { console.log("AutoAssign: Script disabled."); return; }
const targetName = getSetting(SETTINGS_KEY_TARGET, null);
const targetId = targetName ? PRODUCTION_TARGETS[targetName] : null;
if (!targetId) { console.log("AutoAssign: No valid target."); return; }
// --- Idle Count Retrieval ---
const idleNarcos = getIdleNarcoCount();
// ---
if (idleNarcos === null) { console.log("AutoAssign: Cannot get idle count. Exiting."); return; }
// DEBUG: Log the retrieved idle count before confirmation
console.log(`AutoAssign DEBUG: Using idle narco count: ${idleNarcos} for target: ${targetName} (ID: ${targetId})`);
const targetElement = [...document.querySelectorAll('.card-title.text-center.mb-1')].find(el => el.textContent === targetName);
const currentNarcos = parseInt(targetElement.parentElement.querySelector('.assignNarcoInput').value);
let maxCapacity;
if (targetName !== 'Street Crimes') maxCapacity = parseInt(targetElement.parentElement.querySelector('.maxCapacity').textContent);
else maxCapacity = 3000;
if (currentNarcos === maxCapacity) return;
let newNarcos;
newNarcos = idleNarcos + currentNarcos;
if (newNarcos > maxCapacity) newNarcos = maxCapacity;
let displayedNarcos = newNarcos - currentNarcos;
if (idleNarcos > 0) {
showStyledConfirm( `Are you sure you want to quickly assign your Narcos? (${displayedNarcos} to ${targetName})`,
() => { // OK Callback
// DEBUG: Log count just before assignment call
console.log(`AutoAssign DEBUG: OK confirmed. Calling assignNarcos with ID: ${targetId}, Name: ${targetName}, Amount: ${idleNarcos}`);
assignNarcos(targetId, targetName, newNarcos);
},
() => { // Cancel Callback
console.log("AutoAssign DEBUG: User cancelled assignment (Cancel).");
}
);
} else {
console.log("AutoAssign DEBUG: No idle narcos found (count is 0 or less).");
}
}
// --- Main Execution ---
const currentPath = window.location.pathname;
if (currentPath.includes('/settings')) {
setTimeout(setupSettingsPage, 1000);
} else if (currentPath.startsWith('/Production')) {
runAutoAssignLogic();
}
})();