diff --git a/resources/[ERS]/SmartFiresLite/.fxap b/resources/[ERS]/SmartFiresLite/.fxap
index 0099fe9f0..bd5b9a68e 100644
Binary files a/resources/[ERS]/SmartFiresLite/.fxap and b/resources/[ERS]/SmartFiresLite/.fxap differ
diff --git a/resources/[ERS]/SmartFiresLite/cl_smartfires.lua b/resources/[ERS]/SmartFiresLite/cl_smartfires.lua
index 7ab530c01..a4c6e88a3 100644
Binary files a/resources/[ERS]/SmartFiresLite/cl_smartfires.lua and b/resources/[ERS]/SmartFiresLite/cl_smartfires.lua differ
diff --git a/resources/[ERS]/SmartFiresLite/sv_smartfires.lua b/resources/[ERS]/SmartFiresLite/sv_smartfires.lua
index 32f82356e..628b96de7 100644
Binary files a/resources/[ERS]/SmartFiresLite/sv_smartfires.lua and b/resources/[ERS]/SmartFiresLite/sv_smartfires.lua differ
diff --git a/resources/[ERS]/SmartHoseLite/.fxap b/resources/[ERS]/SmartHoseLite/.fxap
index 8e056a434..affe7d6db 100644
Binary files a/resources/[ERS]/SmartHoseLite/.fxap and b/resources/[ERS]/SmartHoseLite/.fxap differ
diff --git a/resources/[ERS]/SmartHoseLite/cl_hose.lua b/resources/[ERS]/SmartHoseLite/cl_hose.lua
index 974a4887f..77300d92e 100644
Binary files a/resources/[ERS]/SmartHoseLite/cl_hose.lua and b/resources/[ERS]/SmartHoseLite/cl_hose.lua differ
diff --git a/resources/[ERS]/SmartHoseLite/sv_exports.lua b/resources/[ERS]/SmartHoseLite/sv_exports.lua
index 13271aff7..741f8947d 100644
Binary files a/resources/[ERS]/SmartHoseLite/sv_exports.lua and b/resources/[ERS]/SmartHoseLite/sv_exports.lua differ
diff --git a/resources/[ERS]/SmartHoseLite/sv_hose.lua b/resources/[ERS]/SmartHoseLite/sv_hose.lua
index 5f041fdb6..37c475191 100644
Binary files a/resources/[ERS]/SmartHoseLite/sv_hose.lua and b/resources/[ERS]/SmartHoseLite/sv_hose.lua differ
diff --git a/resources/[ERS]/ebu_flatbeds_ers/.fxap b/resources/[ERS]/ebu_flatbeds_ers/.fxap
index 120c11e6f..c3dce4805 100644
Binary files a/resources/[ERS]/ebu_flatbeds_ers/.fxap and b/resources/[ERS]/ebu_flatbeds_ers/.fxap differ
diff --git a/resources/[ERS]/ebu_flatbeds_ers/client/client.lua b/resources/[ERS]/ebu_flatbeds_ers/client/client.lua
index e82b25be4..f4b4e5fc0 100644
Binary files a/resources/[ERS]/ebu_flatbeds_ers/client/client.lua and b/resources/[ERS]/ebu_flatbeds_ers/client/client.lua differ
diff --git a/resources/[ERS]/ebu_flatbeds_ers/config.lua b/resources/[ERS]/ebu_flatbeds_ers/config.lua
index 1280acaf5..ef0701638 100644
--- a/resources/[ERS]/ebu_flatbeds_ers/config.lua
+++ b/resources/[ERS]/ebu_flatbeds_ers/config.lua
@@ -81,10 +81,6 @@ Config.flatbed = "flatbed" -- Base game flatbed
Config.flatbedm2 = "flatbedm2" -- https://www.gta5-mods.com/vehicles/freightliner-m2-crew-cab-flatbed-add-on-script-beta
Config.lgc19flatbed = "lgc19flatbed" -- https://forum.cfx.re/t/2019-peterbilt-flatbed/4783413
Config.biftowmfd2 = "biftowmfd2" -- https://mfd.tebex.io/package/6281210
-Config.Gtow = "Gtow" -- https://www.gta5-mods.com/vehicles/peterbilt-337-tuning-by-mfd-fivem
-Config.flatbedm2 = "flatbedm2" -- https://www.gta5-mods.com/vehicles/freightliner-m2-crew-cab-flatbed-add-on-script-beta
-Config.lgc19flatbed = "lgc19flatbed" -- https://forum.cfx.re/t/2019-peterbilt-flatbed/4783413
-Config.biftowmfd2 = "biftowmfd2" -- https://mfd.tebex.io/package/6281210
Config.Gtow = "Gtow"
Config.towy = "towy"
Config.rollback1 = "rollback1"
@@ -105,6 +101,11 @@ Config.gtrailer = "gtrailer"
Config.dotgooseneck = "dotgooseneck"
Config.firef350 = "firef350"
Config.Terrain20tahoe = "Terrain20tahoe"
+
+
+
+
+
-- List any vehicle models here you do not want to be able to be towed
Config.BlacklistedVehs = {
diff --git a/resources/[ERS]/ebu_flatbeds_ers/server/server.lua b/resources/[ERS]/ebu_flatbeds_ers/server/server.lua
index 9c3557834..eeec6d14c 100644
Binary files a/resources/[ERS]/ebu_flatbeds_ers/server/server.lua and b/resources/[ERS]/ebu_flatbeds_ers/server/server.lua differ
diff --git a/resources/[ERS]/night_ers/.fxap b/resources/[ERS]/night_ers/.fxap
index ba4447520..67747aac4 100644
Binary files a/resources/[ERS]/night_ers/.fxap and b/resources/[ERS]/night_ers/.fxap differ
diff --git a/resources/[ERS]/night_ers/NUI/main.js b/resources/[ERS]/night_ers/NUI/main.js
index ad40cddc2..38438cfd6 100644
--- a/resources/[ERS]/night_ers/NUI/main.js
+++ b/resources/[ERS]/night_ers/NUI/main.js
@@ -1,2812 +1,49 @@
-// Global values
-let resourceName = null;
-let language = null;
-let commands = null;
-let firstnames = {};
-let lastnames = {};
-
-let isDisplayingPreCalloutInterface = false;
-let isDisplayingCalloutInterface = false;
-
-// Drag functionality variables
-let isDragMode = false;
-let isDragging = false;
-let dragElement = null;
-let dragOffset = { x: 0, y: 0 };
-
-// UI Layout Mode variables
-let isLayoutMode = false;
-let layoutElements = {};
-let visibleLayoutElements = new Set();
-
-// Enhanced layout system variables
-let originalStyles = new Map(); // Store original styles before layout mode
-let layoutBoundaries = { left: 20, top: 20, right: 20, bottom: 20 }; // Screen boundaries
-let snapGrid = { enabled: true, size: 10 }; // Grid snapping
-let collisionDetection = { enabled: true }; // Element collision detection
-let dimensionValidation = { enabled: true }; // Validate element dimensions for real vs placeholder content
-
-window.addEventListener('message', (event) => {
- const data = event.data;
-
- if (data.transactionType == "playSound") {
- PlayNUISound(data.transactionFolder, data.transactionFile, data.transactionVolume)
- }
-
- if (data.type == "init") {
- if (typeof $ !== 'undefined') {
- resourceName = data.resourcename
- language = data.language
- commands = data.commands
- firstnames = data.firstnames
- lastnames = data.lastnames
-
- $.post(`https://${resourceName}/initComplete`, JSON.stringify({
- complete: true
- }));
- } else {
- console.log("Script is still loading...")
- };
- }
-
- if (data.type == "togglecalloutinfo") {
- toggleCalloutInfo();
- }
-
- if (data.type == "toggleUILayoutMode") {
- console.log("Received toggleUILayoutMode message from Lua");
- toggleUILayoutMode();
- }
-
- if (data.type == "emergencyUICleanup") {
- console.log("Received emergencyUICleanup message from Lua");
- clearModuleData();
- emergencyUICleanup();
- }
-
- if (data.type == "clearInformationModulesOnShiftEnd") {
- clearModuleData();
- }
-
- if (data.type == "ersselectionmenu") {
- var display = data.display
- var permissions = data.permissions
- ToggleERSSelectionMenu(display, permissions)
- }
-
- if (data.type == "radialmenu") {
- var display = data.display
- ToggleRadialMenu(display)
- }
-
- if (data.type == "pursuitradialmenu") {
- var display = data.display
- TogglePursuitRadialMenu(display)
- }
-
- if (data.type == "pursuitmode") {
- var display = data.display
- var displayhotkeyhint = data.displayhotkeyhint
- var zoomhotkey = data.zoomhotkey
- var backuphotkey = data.backuphotkey
- TogglePursuitModeUI(display, displayhotkeyhint, zoomhotkey, backuphotkey)
- }
-
- if (data.type == "dualsteeringmode") {
- var display = data.display
- ToggleDualSteeringMode(display)
- }
-
- if (data.type == "hotkeyhintprompt") {
- var display = data.display
- var hotkeys = data.hotkeys
- var time = data.time
- ToggleHotKeyHintPrompt(display, hotkeys, language, time)
- }
-
- if (data.type == "dispatchmessage") {
- var display = data.display
- var hotkeys = data.hotkeys
- var messagetype = data.messagetype
- var calloutdata = data.calloutdata
- var message = data.message
- var time = data.time
- var toggle = data.toggle
- AddMessageToDispatchQueue(display, hotkeys, messagetype, calloutdata, time, message, toggle)
- }
-
- if (data.type == "calloutprompt") {
- var display = data.display
- var calloutdata = data.calloutdata
- var hotkeys = data.hotkeys
- var time = data.time
- var serviceType = data.serviceType
- ToggleCalloutDisplayPrompt(display, hotkeys, language, time, calloutdata, serviceType)
- }
-
- if (data.type == "calloutpreinterface") {
- var display = data.display
- var hotkeys = data.hotkeys
- var calloutdata = data.calloutdata
- TogglePreCalloutInterface(display, hotkeys, calloutdata)
- }
-
- if (data.type == "calloutinterface") {
- var display = data.display
- var hotkeys = data.hotkeys
- var pedCount = data.pedCount
- var vehicleCount = data.vehicleCount
- var objectCount = data.objectCount
- var propCount = data.propCount
- var fireCount = data.fireCount
- var smokeCount = data.smokeCount
-
- var calloutdata = data.calloutdata
-
- var pedOriginalCount = data.pedOriginalCount
- var vehOriginalCount = data.vehOriginalCount
- var objOriginalCount = data.objOriginalCount
- var propOriginalCount = data.propOriginalCount
- var fireOriginalCount = data.fireOriginalCount
- var smokeOriginalCount = data.smokeOriginalCount
-
- ToggleCalloutInterface(display, hotkeys,pedCount, vehicleCount, objectCount, propCount, fireCount, smokeCount, calloutdata, pedOriginalCount, vehOriginalCount, objOriginalCount, propOriginalCount, fireOriginalCount, smokeOriginalCount)
- }
-
- if (data.type == "unifiedprompt") {
- var display = data.display
- var promptType = data.promptType
- var hotkey = data.hotkey
- var message = data.message
- var time = data.time
- DisplayUnifiedPrompt(display, promptType, hotkey, message, time)
- }
-
- if (data.type == "interactionmodule") {
- var display = data.display
- var isDead = data.ispeddeadordying
- var service = data.service
- DisplayPedInteractionModule(display, isDead, service)
- }
-
- if (data.type == "idcardprompt") {
- var display = data.display
- var personaldata = data.pedpersonaldata
- var showdatabasecheck = data.showdatabasecheck
- DisplayPedIdCard(display, personaldata, showdatabasecheck)
- }
-
- if (data.type == "inventoryprompt") {
- var display = data.display
- var itemList = data.itemlist
- DisplayPedInventory(display, itemList)
- }
-
- if(data.type == "vehicleinfoprompt") {
- var display = data.display
- var vehicleData = data.vehicleData
- var DisableTaxAndMOT = data.DisableTaxAndMOT
- DisplayVehicleInfo(display, vehicleData, DisableTaxAndMOT)
- }
-
- if (data.type == "redisplaylastmodule") {
- redisplayLastModule()
- }
-
- if (data.type == "togglequestionsmodule") {
- var display = data.display
- var questions = data.questions
- ToggleQuestionsModule(display, questions)
- }
-
- if (data.type == "updateanswers") {
- var display = data.display
- var answers = data.answers
- UpdateAnswers(display, answers)
- }
-
- if (data.type == "addorremovewaypoint") {
- var addOrRemove = data.addwaypoint
- AddWaypoint(addOrRemove);
- }
-
- if (data.type == "updatewaypoint") {
- var scaleX = data.scaleX
- var scaleY = data.scaleY
- var distanceText = data.distanceText
- UpdateWaypointPosition(scaleX, scaleY, distanceText);
- }
-
- if (data.type == "areyousure") {
- var display = data.display
- DisplayAreYouSurePopup(display)
- }
-
- if (data.type == "gearmenu") {
- var display = data.display
- var locationData = data.locationdata
- DisplayGearMenu(display, locationData)
- }
-
- if (data.type == "updatezonechange") {
- var lastZone = data.lastZone
- var currentZone = data.currentZone
- UpdateZoneChangeUI(lastZone, currentZone)
- }
-
- if (data.type === 'updatewaypoints') {
- updateWaypoints(data);
- }
-});
-
-// FUNCTIONS
-
-var zoneChangeTimeout = null;
-let zoneChangeQueue = [];
-let isAnimating = false;
-
-function UpdateZoneChangeUI(oldZone, newZone) {
- zoneChangeQueue.push({ oldZone, newZone });
- if (!isAnimating) {
- processNextZoneChange();
- }
-}
-
-function processNextZoneChange() {
- if (zoneChangeQueue.length === 0) {
- isAnimating = false;
- return;
- }
-
- isAnimating = true;
- const { oldZone, newZone } = zoneChangeQueue.shift();
-
- const zoneChangeUI = document.getElementById('zone-change-ui');
- if (!zoneChangeUI) {
- processNextZoneChange();
- return;
- }
-
- const oldZoneElement = zoneChangeUI.querySelector('.old-zone');
- const newZoneElement = zoneChangeUI.querySelector('.new-zone');
-
- if (!oldZoneElement || !newZoneElement) {
- processNextZoneChange();
- return;
- }
-
- // Clear any existing timeout
- if (zoneChangeTimeout) {
- clearTimeout(zoneChangeTimeout);
- }
-
- // Reset the animation state
- zoneChangeUI.classList.remove('show');
- newZoneElement.classList.remove('show');
-
- // Set the new zone values
- oldZoneElement.textContent = oldZone ? oldZone : "N/A";
- newZoneElement.textContent = newZone ? newZone : "N/A";
-
- // Trigger reflow to ensure the animation restarts
- void zoneChangeUI.offsetWidth;
-
- // Start the new animation
- zoneChangeUI.classList.add('show');
- newZoneElement.classList.add('show');
-
- // Set a new timeout
- zoneChangeTimeout = setTimeout(() => {
- zoneChangeUI.classList.remove('show');
- newZoneElement.classList.remove('show');
-
- // Process the next zone change after the animation is complete
- setTimeout(processNextZoneChange, 500); // Add a small delay between animations
- }, 4000);
-}
-
-let escapeEventListenerAdded = false;
-
-function DisplayAreYouSurePopup(display) {
- if (display) {
- // Remove any previous modals
- $('#are-you-sure-modal').remove();
-
- // HTML
- const modal = `
-
-
-
-
-
-
${language.CompletingCalloutCannotBeUndone}
-
-
-
-
-
- `;
-
- $('body').append(modal);
-
- // Initialize the modal with static backdrop and disabled keyboard interaction
- $('#are-you-sure-modal').modal({
- backdrop: 'static',
- keyboard: false
- });
-
- // Show the modal explicitly
- $('#are-you-sure-modal').modal('show');
-
- // Handle Escape key press only when the modal is open
- $('#are-you-sure-modal').on('shown.bs.modal', function() {
- if (!escapeEventListenerAdded) {
- $(document).on('keydown', function(event) {
- if (event.key === "Escape") {
- // Close the modal
- $('#are-you-sure-modal').modal('hide');
- // Trigger the same action as the "No" button click
- handleNoClick();
- // Ensure the event doesn't propagate further
- event.stopPropagation();
- }
- });
- escapeEventListenerAdded = true;
- }
- }).on('hidden.bs.modal', function() {
- // Remove the Escape key press event listener when the modal is closed
- $(document).off('keydown');
- escapeEventListenerAdded = false;
- });
-
- } else {
- $('#are-you-sure-modal').remove();
- }
-}
-
-
-// Function to handle 'No' button click
-function handleNoClick() {
- $.post(`https://${resourceName}/AreYouSure`, JSON.stringify({
- areyousure: false
- }));
- $('#are-you-sure-modal').modal('hide');
-}
-
-// Function to handle 'Yes' button click
-function handleYesClick() {
- $.post(`https://${resourceName}/AreYouSure`, JSON.stringify({
- areyousure: true
- }));
- $('#are-you-sure-modal').modal('hide');
-}
-
-function DisplayPedInteractionModule(display, isDead, service) { // service can be: police, fire, ambulance or tow.
- if (display) {
- DisplayUnifiedPrompt(false)
- if (isDead) {
- $("#ped-interaction-module").empty();
- $("#ped-interaction-module").show();
-
- //HTML
- $("#ped-interaction-module").append(`
- ${language.InteractionOptions}
-
-
-
-
- ${[
- { id: 'identify', label: language.IdentifyDeadPed, explanation: language.IdentifyDeadPedExplanation },
- { id: 'drag', label: language.DragPed, explanation: language.DragPedExplanation },
- { id: 'massivebleeding', label: language.CheckMassiveBleeding, explanation: language.CheckMassiveExplanation },
- { id: 'airway', label: language.CheckAirway, explanation: language.CheckAirwayExplanation },
- { id: 'breathing', label: language.CheckBreathing, explanation: language.CheckBreathingExplanation },
- { id: 'circulation', label: language.CheckCirculation, explanation: language.CheckCirculationExplanation },
- { id: 'hypothermia', label: language.CheckHypothermia, explanation: language.CheckHypothermiaExplanation },
- { id: 'cpr', label: language.PerformCPR, explanation: language.PerformCPRExplanation },
- { id: 'putonstretcher', label: language.PutOnStretcher, explanation: language.PutOnStretcherExplanation },
- { id: 'takeoffstretcher', label: language.TakeOffStretcher, explanation: language.TakeOffStretcherExplanation },
- { id: 'bodybag', label: language.PutInBodyBag, explanation: language.PutInBodyBagExplanation }
- ].map(item => `
-
-
- ${item.label}
-
-
- ${item.explanation}
-
-
- `).join('')}
-
-
-
-
-
-
-
- ${language.ExitInteraction}
-
-
-
- `);
-
- // Apply sound effects to all buttons
- const buttonIds = [
- 'identify', 'drag', 'massivebleeding', 'airway', 'breathing', 'circulation', 'hypothermia', 'cpr', 'putonstretcher', 'takeoffstretcher', 'bodybag',
- 'exit'
- ];
- buttonIds.forEach(id => addSoundOnHoverEventListener(`p-btn-${id}`));
-
- } else {
- $("#ped-interaction-module").empty();
- $("#ped-interaction-module").show();
-
- // Per service we need to show different buttons.
- var buttonsPerService = {
- police: [
- { id: 'greet', label: language.Greet, explanation: language.GreetExplanation },
- { id: 'id', label: language.AskForId, explanation: language.AskForIdExplanation },
- { id: 'questioning', label: language.Question, explanation: language.QuestionExplanation },
- { id: 'breathalyze', label: language.Breathalyze, explanation: language.BreathalyzeExplanation },
- { id: 'drugtest', label: language.DrugTest, explanation: language.DrugTestExplanation },
- { id: 'warn', label: language.Warn, explanation: language.WarnExplanation },
- { id: 'fine', label: language.Fine, explanation: language.FineExplanation },
- { id: 'grab', label: language.Grab, explanation: language.GrabExplanation },
- { id: 'getout', label: language.GetOut, explanation: language.GetOutExplanation },
- { id: 'follow', label: language.AskToFollow, explanation: language.AskToFollowExplanation },
- { id: 'wait', label: language.AskToWait, explanation: language.AskToWaitExplanation },
- { id: 'handsup', label: language.HandsUp, explanation: language.HandsUpExplanation },
- { id: 'search', label: language.Search, explanation: language.SearchExplanation },
- { id: 'cuff', label: language.Cuff, explanation: language.CuffExplanation },
- { id: 'putinvehicle', label: language.PutInVehicle, explanation: language.PutInVehicleExplanation }
- ],
- ambulance: [
- { id: 'greet', label: language.Greet, explanation: language.GreetExplanation },
- { id: 'questioning', label: language.Question, explanation: language.QuestionExplanation },
- { id: 'breathalyze', label: language.Breathalyze, explanation: language.BreathalyzeExplanation },
- { id: 'drugtest', label: language.DrugTest, explanation: language.DrugTestExplanation },
- { id: 'getout', label: language.GetOut, explanation: language.GetOutExplanation },
- { id: 'follow', label: language.AskToFollow, explanation: language.AskToFollowExplanation },
- { id: 'wait', label: language.AskToWait, explanation: language.AskToWaitExplanation },
- { id: 'putinvehicle', label: language.PutInVehicle, explanation: language.PutInVehicleExplanation }
- ],
- fire: [
- { id: 'greet', label: language.Greet, explanation: language.GreetExplanation },
- { id: 'questioning', label: language.Question, explanation: language.QuestionExplanation },
- { id: 'breathalyze', label: language.Breathalyze, explanation: language.BreathalyzeExplanation },
- { id: 'drugtest', label: language.DrugTest, explanation: language.DrugTestExplanation },
- { id: 'getout', label: language.GetOut, explanation: language.GetOutExplanation },
- { id: 'follow', label: language.AskToFollow, explanation: language.AskToFollowExplanation },
- { id: 'wait', label: language.AskToWait, explanation: language.AskToWaitExplanation },
- { id: 'putinvehicle', label: language.PutInVehicle, explanation: language.PutInVehicleExplanation }
- ],
- tow: [
- { id: 'greet', label: language.Greet, explanation: language.GreetExplanation },
- { id: 'questioning', label: language.Question, explanation: language.QuestionExplanation },
- { id: 'getout', label: language.GetOut, explanation: language.GetOutExplanation },
- { id: 'follow', label: language.AskToFollow, explanation: language.AskToFollowExplanation },
- { id: 'wait', label: language.AskToWait, explanation: language.AskToWaitExplanation },
- { id: 'putinvehicle', label: language.PutInVehicle, explanation: language.PutInVehicleExplanation }
- ]
- }
-
- // HTML
- $("#ped-interaction-module").append(`
- ${language.InteractionOptions}
-
-
-
-
- ${(buttonsPerService[service] || buttonsPerService.police).map(item => `
-
-
- ${item.label}
-
-
- ${item.explanation}
-
-
- `).join('')}
-
-
-
-
-
-
-
- ${language.StopInteraction}
- ${language.ExitInteraction}
- ${service === 'police' ? `${language.SendToCustody} ` : ''}
-
-
-
- `);
-
- // Apply sound on hover to all buttons
- const serviceButtons = buttonsPerService[service] || buttonsPerService.police;
- const buttonIds = [
- ...serviceButtons.map(item => item.id),
- 'end', 'exit',
- ...(service === 'police' ? ['custody'] : [])
- ];
- buttonIds.forEach(id => addSoundOnHoverEventListener(`p-btn-${id}`));
- }
- } else {
- $("#ped-interaction-module").hide();
- }
-}
-
-function PedInteraction(intType) {
- $.post(`https://${resourceName}/pedInteraction`, JSON.stringify({
- interactionType: intType
- }))
-}
-
-function addSoundOnHoverEventListener(buttonId) {
- var button = document.getElementById(buttonId);
- button.addEventListener('mouseenter', function() {
- PlayNUISound('generic-sounds', "rollover", 0.5);
- });
-}
-
-var unifiedPromptTimeout;
-
-function DisplayUnifiedPrompt(display, promptType, hotkey, message, time) {
- if (display) {
- $("#unified-prompt").show();
-
- clearTimeout(unifiedPromptTimeout);
-
- // Define prompt configurations
- const promptConfigs = {
- 'pedinteraction': {
- icon: '๐ฌ',
- color: 'text-warning',
- text: language.ToInteract,
- timeout: 1500
- },
- 'injuredped': {
- icon: '๐ฉบ',
- color: 'text-danger',
- text: language.ToPerformCPR,
- timeout: 1500
- },
- 'impound': {
- icon: '๐',
- color: 'text-danger',
- text: language.ToInteractImpound,
- timeout: 1500
- },
- 'gear': {
- icon: '๐',
- color: 'text-danger',
- text: language.ToInteractGear,
- timeout: 1500
- },
- 'stretcher': {
- icon: '๐ฅ',
- color: 'text-info',
- text: language.ToUseStretcherVeh,
- timeout: 1500
- },
- 'objectcleanup': {
- icon: '๐งน',
- color: 'text-success',
- text: language.ToCleanupObject,
- timeout: 1500
- },
- 'spikesvehicle': {
- icon: '๐ข',
- color: 'text-warning',
- text: message || '',
- timeout: time || 1500
- }
- };
-
- const config = promptConfigs[promptType] || promptConfigs['pedinteraction'];
-
- $("#unified-prompt").html(`
- ${config.icon} ${language.Press} ${hotkey} ${config.text}
- `);
-
- unifiedPromptTimeout = setTimeout(function() {
- $("#unified-prompt").hide();
- }, config.timeout);
-
- } else {
- $("#unified-prompt").hide();
- }
-}
-
-// Track last displayed module for TAB key re-display
-var lastDisplayedModule = null; // 'idcard', 'vehicle', or 'inventory'
-var lastIdCardData = null;
-var lastVehicleData = null;
-var lastInventoryData = null;
-
-// Track database check completion states for each module
-var idCardDbCheckCompleted = false;
-var vehicleDbCheckCompleted = false;
-
-var idCardTimeout;
-var vehicleInfoTimeout;
-var dbCheckTimeout;
-var vehicleDbCheckTimeout;
-var moduleClearTimeout; // Timeout to clear module data if hidden for > 1 minute
-var moduleProgressInterval; // Interval to update progress bar
-var moduleClearStartTime; // Timestamp when module clear timer started
-
-function DisplayPedIdCard(display, personaldata, showdatabasecheck, skipDbCheckAnimation) {
- if (display) {
- // Hide vehicle info.
- $("#vehicle-info").hide();
- // Hide inventory
- $("#ped-interaction-inventory").hide();
-
- clearTimeout(idCardTimeout);
-
- // Only clear dbCheckTimeout if we're not preserving state
- if (!skipDbCheckAnimation) {
- clearTimeout(dbCheckTimeout);
- idCardDbCheckCompleted = false;
- }
-
- $("#ped-interaction-id-card").empty();
-
- var profilePicture = personaldata.ProfilePicture || 'N/A';
- var firstName = personaldata.FirstName || 'N/A';
- var lastName = personaldata.LastName || 'N/A';
- var dob = personaldata.DOB || 'N/A';
- var gender = personaldata.Gender || 'N/A';
- var email = personaldata.Email || 'N/A';
- var phone = personaldata.PhoneNumber || 'N/A';
- var country = personaldata.Country || 'N/A';
- var state = personaldata.State || 'N/A';
- var city = personaldata.City || 'N/A';
- var postalcode = personaldata.PostalCode || 'N/A';
- var address = personaldata.Address || 'N/A';
- var addressType = personaldata.AddressType || 'N/A';
- var nationality = personaldata.Nationality || 'N/A';
- var flagsOrMarkers = personaldata.FlagsOrMarkers // This is a list of keys which are true or false, I want each one to be displayed....
- var driversLicense = personaldata.License_Car || 'N/A';
- var driversLicenseColour = personaldata.License_Car_Colour || 'text-light';
- var driversLicenseIcon = personaldata.License_Car_Icon || 'fas fa-car';
- var bikeLicense = personaldata.License_Bike || 'N/A';
- var bikeLicenseColour = personaldata.License_Bike_Colour || 'text-light';
- var bikeLicenseIcon = personaldata.License_Bike_Icon || 'fas fa-bicycle';
- var boatLicense = personaldata.License_Boat || 'N/A';
- var boatLicenseColour = personaldata.License_Boat_Colour || 'text-light';
- var boatLicenseIcon = personaldata.License_Boat_Icon || 'fas fa-ship';
- var truckLicense = personaldata.License_Truck || 'N/A';
- var truckLicenseColour = personaldata.License_Truck_Colour || 'text-light';
- var truckLicenseIcon = personaldata.License_Truck_Icon || 'fas fa-truck';
- var pilotLicense = personaldata.License_Pilot || 'N/A';
- var pilotLicenseColour = personaldata.License_Pilot_Colour || 'text-light';
- var pilotLicenseIcon = personaldata.License_Pilot_Icon || 'fas fa-plane';
-
- // Store data for TAB key re-display
- lastDisplayedModule = 'idcard';
- lastIdCardData = {
- personaldata: personaldata,
- showdatabasecheck: showdatabasecheck
- };
-
- // Modern Bootstrap 5.2.3 Card Design
- // DON'T use isolation: isolate - it causes text blurriness
- $("#ped-interaction-id-card").append(`
-
-
-
-
- ${language.FullName}
- ${firstName} ${lastName}
-
-
- ${language.DOB}
- ${dob}
-
-
-
- `);
-
- $("#ped-interaction-id-card").show();
-
- if (showdatabasecheck) {
- // Always create the database-check container first
- // DON'T use isolation: isolate on the card itself - it causes text blurriness
- $("#ped-interaction-id-card").append(`
-
-
- `);
-
- // Check if database check was already completed
- if (idCardDbCheckCompleted && skipDbCheckAnimation) {
- // Show completed results immediately
- renderIdCardDatabaseResults(personaldata, firstName, lastName, dob, profilePicture, nationality, gender, address, city, state, postalcode, country, email, phone, driversLicense, driversLicenseColour, bikeLicense, bikeLicenseColour, boatLicense, boatLicenseColour, truckLicense, truckLicenseColour, pilotLicense, pilotLicenseColour, flagsOrMarkers);
- } else {
- // Show loading spinner
- $("#database-check").html(`
-
-
-
-
-
-
${language.RunningDatabaseCheck}
-
-
- `);
-
- // Delay before results & Display results
- dbCheckTimeout = setTimeout(function() {
- idCardDbCheckCompleted = true;
- $("#initial-check").remove();
- renderIdCardDatabaseResults(personaldata, firstName, lastName, dob, profilePicture, nationality, gender, address, city, state, postalcode, country, email, phone, driversLicense, driversLicenseColour, bikeLicense, bikeLicenseColour, boatLicense, boatLicenseColour, truckLicense, truckLicenseColour, pilotLicense, pilotLicenseColour, flagsOrMarkers);
- }, 3000);
- }
- }
-
- // Hide the ID card after a certain period
- idCardTimeout = setTimeout(function() {
- $("#ped-interaction-id-card").hide();
- updateModuleIndicator();
- scheduleModuleClearIfHidden();
- }, 15000);
-
- updateModuleIndicator();
-
- } else {
- $("#ped-interaction-id-card").hide();
- updateModuleIndicator();
- }
-}
-
-// Separate function to render ID card database results
-function renderIdCardDatabaseResults(personaldata, firstName, lastName, dob, profilePicture, nationality, gender, address, city, state, postalcode, country, email, phone, driversLicense, driversLicenseColour, bikeLicense, bikeLicenseColour, boatLicense, boatLicenseColour, truckLicense, truckLicenseColour, pilotLicense, pilotLicenseColour, flagsOrMarkers) {
- // Completely clear and replace content to reset rendering context
- var dbCheckElement = document.getElementById('database-check');
- if (dbCheckElement) {
- // Remove all content including loading indicator
- dbCheckElement.innerHTML = '';
- // Force a reflow to clear any rendering contexts
- void dbCheckElement.offsetHeight;
- }
-
- $("#database-check").html(`
-
-
-
-
-
-
${firstName} ${lastName}
- ${dob}
-
-
-
-
-
-
-
- ${language.Nationality}
- ${nationality}
-
-
-
-
- ${language.Gender}
- ${gender}
-
-
-
-
- ${language.Address}
- ${address}, ${city} ${state} ${postalcode}, ${country}
-
-
-
-
- ${language.Email}
- ${email}
-
-
- ${language.PhoneNumber}
- ${phone}
-
-
-
-
-
-
-
-
${language.Licenses}
-
-
- ${driversLicense}
-
-
- ${bikeLicense}
-
-
- ${boatLicense}
-
-
- ${truckLicense}
-
-
- ${pilotLicense}
-
-
-
-
- ${flagsOrMarkers && Object.keys(flagsOrMarkers).some(key => flagsOrMarkers[key]) ? `
-
-
${language.FlagsOrMarkers}
-
- ${flagsOrMarkers.armed_and_dangerous ? `
${language.armed_and_dangerous}
` : ''}
- ${flagsOrMarkers.assault ? `
${language.assault}
` : ''}
- ${flagsOrMarkers.burglary ? `
${language.burglary}
` : ''}
- ${flagsOrMarkers.drug_related ? `
${language.drug_related}
` : ''}
- ${flagsOrMarkers.gang_affiliation ? `
${language.gang_affiliation}
` : ''}
- ${flagsOrMarkers.homicide ? `
${language.homicide}
` : ''}
- ${flagsOrMarkers.kidnapping ? `
${language.kidnapping}
` : ''}
- ${flagsOrMarkers.mental_health_issues ? `
${language.mental_health_issues}
` : ''}
- ${flagsOrMarkers.sex_offense ? `
${language.sex_offense}
` : ''}
- ${flagsOrMarkers.terrorism ? `
${language.terrorism}
` : ''}
- ${flagsOrMarkers.theft ? `
${language.theft}
` : ''}
- ${flagsOrMarkers.traffic_violation ? `
${language.traffic_violation}
` : ''}
- ${flagsOrMarkers.wanted_person ? `
${language.wanted_person}
` : ''}
- ${flagsOrMarkers.other ? `
${language.other}
` : ''}
- ${flagsOrMarkers.active_warrant ? `
${language.active_warrant}
` : ''}
-
-
- ` : ''}
-
- `);
-
- // Force browser reflow and repaint to ensure text renders crisply
- var databaseCheck = document.getElementById('database-check');
- if (databaseCheck) {
- // Force reflow
- void databaseCheck.offsetHeight;
- // Reset any transform that might affect rendering
- databaseCheck.style.isolation = 'auto';
- // Force repaint by toggling a property
- var originalTransform = databaseCheck.style.transform;
- databaseCheck.style.transform = 'translateZ(0)';
- // Use requestAnimationFrame to ensure browser has processed the change
- requestAnimationFrame(function() {
- databaseCheck.style.transform = originalTransform || 'translateZ(0)';
- });
- }
-}
-
-function DisplayVehicleInfo(display, vehicleData, DisableTaxAndMOT, skipDbCheckAnimation) {
- if (display) {
- // Hide ID card
- $("#ped-interaction-id-card").hide();
- // Hide inventory
- $("#ped-interaction-inventory").hide();
-
- clearTimeout(vehicleInfoTimeout);
-
- // Only clear vehicleDbCheckTimeout if we're not preserving state
- if (!skipDbCheckAnimation) {
- clearTimeout(vehicleDbCheckTimeout);
- vehicleDbCheckCompleted = false;
- }
-
- $("#vehicle-info").empty();
-
- // Vehicle Data
- var data = {
- vehNetId: vehicleData.vehNetId,
- license_plate: vehicleData.license_plate,
- model: vehicleData.model,
- model_hash: vehicleData.model_hash,
- vehicle_class: vehicleData.vehicle_class,
- vehicle_class_from_name: vehicleData.vehicle_class_from_name,
- color: vehicleData.color,
- color_secondary: vehicleData.color_secondary,
- build_year: vehicleData.build_year,
- tax: vehicleData.tax,
- mot: vehicleData.mot,
- insurance: vehicleData.insurance,
- stolen: vehicleData.stolen,
- bolo: vehicleData.bolo,
- bolo_description: vehicleData.bolo_description,
- owner_name: vehicleData.owner_name,
- }
-
- // Store data for TAB key re-display
- lastDisplayedModule = 'vehicle';
- lastVehicleData = {
- vehicleData: vehicleData,
- DisableTaxAndMOT: DisableTaxAndMOT
- };
-
- // Modern Bootstrap 5.2.3 Vehicle Info Card
- // DON'T use isolation: isolate - it causes text blurriness
- $("#vehicle-info").append(`
-
-
-
-
- ${language.VehiclePlate}
- ${data.license_plate}
-
-
- ${language.VehicleModel}
- ${data.model}
-
-
-
- `);
-
- // Always create the database-check container first
- // DON'T use isolation: isolate on the card itself - it causes text blurriness
- $("#vehicle-info").append(`
-
-
- `);
-
- $("#vehicle-info").show();
-
- // Check if database check was already completed
- if (vehicleDbCheckCompleted && skipDbCheckAnimation) {
- // Show completed results immediately
- renderVehicleDatabaseResults(data, DisableTaxAndMOT);
- } else {
- // Show loading spinner
- $("#vehicle-info-database-check").html(`
-
-
-
-
-
-
${language.RunningDatabaseCheck}
-
-
- `);
-
- vehicleDbCheckTimeout = setTimeout(function() {
- vehicleDbCheckCompleted = true;
- renderVehicleDatabaseResults(data, DisableTaxAndMOT);
- }, 5000);
- }
-
- // Hide the vehicle info after a certain period
- vehicleInfoTimeout = setTimeout(function() {
- $("#vehicle-info").hide();
- updateModuleIndicator();
- scheduleModuleClearIfHidden();
- }, 15000);
-
- updateModuleIndicator();
-
- } else {
- $("#vehicle-info").hide();
- updateModuleIndicator();
- }
-}
-
-// Separate function to render vehicle database results
-function renderVehicleDatabaseResults(data, DisableTaxAndMOT) {
- // Completely clear and replace content to reset rendering context
- var vehicleDbCheckElement = document.getElementById('vehicle-info-database-check');
- if (vehicleDbCheckElement) {
- // Remove all content including loading indicator
- vehicleDbCheckElement.innerHTML = '';
- // Force a reflow to clear any rendering contexts
- void vehicleDbCheckElement.offsetHeight;
- }
-
- $("#vehicle-info-database-check").html(`
-
-
-
-
-
- ${language.VehicleOwner}
- ${data.owner_name}
-
-
-
-
- ${language.VehicleBuildYear}
- ${data.build_year}
-
-
-
-
- ${language.VehicleColor}
- ${data.color}
-
-
-
-
- ${language.VehicleColorSecondary}
- ${data.color_secondary}
-
-
-
- ${DisableTaxAndMOT ? "" : `
-
-
- ${language.VehicleTax}
-
- ${data.tax ? language.Paid : language.NotPaid}
-
-
-
-
-
- ${language.VehicleMOT}
-
- ${data.mot ? language.Passed : language.Failed}
-
-
-
- `}
-
-
- ${language.VehicleInsurance}
-
- ${data.insurance ? language.Valid : language.Invalid}
-
-
-
-
-
- ${language.VehicleStolen}
-
- ${data.stolen ? language.Yes : language.No}
-
-
-
-
-
- ${language.VehicleBolo}
-
- ${data.bolo ? language.Yes : language.No}
-
-
-
- ${!data.bolo ? "" : `
-
-
-
${language.VehicleBoloDescription}
-
${wrapText(data.bolo_description ? data.bolo_description : "-", 50)}
-
-
- `}
-
-
- `);
-
- // Force browser reflow and repaint to ensure text renders crisply
- var vehicleDbCheck = document.getElementById('vehicle-info-database-check');
- if (vehicleDbCheck) {
- // Force reflow
- void vehicleDbCheck.offsetHeight;
- // Reset any transform that might affect rendering
- vehicleDbCheck.style.isolation = 'auto';
- // Force repaint by toggling a property
- var originalTransform = vehicleDbCheck.style.transform;
- vehicleDbCheck.style.transform = 'translateZ(0)';
- // Use requestAnimationFrame to ensure browser has processed the change
- requestAnimationFrame(function() {
- vehicleDbCheck.style.transform = originalTransform || 'translateZ(0)';
- });
- }
-}
-
-var inventoryTimeout;
-function DisplayPedInventory(display, itemList) {
- if (display) {
- // Hide ID card
- $("#ped-interaction-id-card").hide();
- // Hide vehicle info
- $("#vehicle-info").hide();
-
- clearTimeout(inventoryTimeout);
-
- $("#ped-interaction-inventory").empty();
-
- // Store data for TAB key re-display
- lastDisplayedModule = 'inventory';
- lastInventoryData = {
- itemList: itemList
- };
-
- // Modern Bootstrap 5.2.3 Inventory Card
- $("#ped-interaction-inventory").append(`
-
- `);
-
- if (itemList.length === 0) {
- $("#inventory-list-body").append(`
-
- `);
- } else {
- $.each(itemList, function (key, v) {
- var isIllegal = v.illegal;
- var itemClass = isIllegal ? 'border-danger border-opacity-50' : 'border-secondary border-opacity-25';
- var textClass = isIllegal ? 'text-danger' : 'text-light';
- var iconClass = isIllegal ? 'fas fa-exclamation-triangle text-danger' : 'fas fa-cube text-info';
-
- var listItem = `
-
-
-
- ${v.name}
- ${isIllegal ? 'Illegal ' : ''}
-
-
- `;
- $("#inventory-list-body").append(listItem);
- });
- }
-
- $("#ped-interaction-inventory").show();
-
- inventoryTimeout = setTimeout(function() {
- $("#ped-interaction-inventory").hide();
- updateModuleIndicator();
- scheduleModuleClearIfHidden();
- }, 15000);
-
- updateModuleIndicator();
-
- } else {
- $("#ped-interaction-inventory").hide();
- updateModuleIndicator();
- }
-}
-
-// Function to clear module data when shift ends
-function clearModuleData() {
- // Clear stored module data
- lastDisplayedModule = null;
- lastIdCardData = null;
- lastVehicleData = null;
- lastInventoryData = null;
-
- // Reset database check completion states
- idCardDbCheckCompleted = false;
- vehicleDbCheckCompleted = false;
-
- // Clear any active timeouts
- clearTimeout(idCardTimeout);
- clearTimeout(vehicleInfoTimeout);
- clearTimeout(inventoryTimeout);
- clearTimeout(dbCheckTimeout);
- clearTimeout(vehicleDbCheckTimeout);
- clearTimeout(moduleClearTimeout);
- stopModuleProgressBar();
-
- // Hide any visible modules
- $("#ped-interaction-id-card").hide();
- $("#vehicle-info").hide();
- $("#ped-interaction-inventory").hide();
-
- // Hide the module indicator
- $("#module-indicator").fadeOut(200);
-}
-
-// Function to schedule clearing module data if hidden for > 1 minute
-function scheduleModuleClearIfHidden() {
- // Clear any existing timeout and interval
- clearTimeout(moduleClearTimeout);
- clearInterval(moduleProgressInterval);
-
- // Record start time for progress bar
- moduleClearStartTime = Date.now();
-
- // Start progress bar animation
- startModuleProgressBar();
-
- // Set new timeout to clear after 60 seconds
- moduleClearTimeout = setTimeout(function() {
- // Only clear if module is still hidden
- if (lastDisplayedModule) {
- var isCurrentlyVisible = false;
-
- if (lastDisplayedModule === 'idcard' && $("#ped-interaction-id-card").is(":visible")) {
- isCurrentlyVisible = true;
- } else if (lastDisplayedModule === 'vehicle' && $("#vehicle-info").is(":visible")) {
- isCurrentlyVisible = true;
- } else if (lastDisplayedModule === 'inventory' && $("#ped-interaction-inventory").is(":visible")) {
- isCurrentlyVisible = true;
- }
-
- // Clear module data if still hidden after 60 seconds
- if (!isCurrentlyVisible) {
- clearModuleData();
- }
- }
- }, 30000); // 30 seconds
-}
-
-// Function to start/update progress bar animation
-function startModuleProgressBar() {
- // Clear any existing interval
- clearInterval(moduleProgressInterval);
-
- // Update progress bar every 100ms for smooth animation
- moduleProgressInterval = setInterval(function() {
- if (!moduleClearStartTime || !lastDisplayedModule) {
- clearInterval(moduleProgressInterval);
- return;
- }
-
- var elapsed = Date.now() - moduleClearStartTime;
- var remaining = Math.max(0, 30000 - elapsed);
- var progress = (remaining / 30000) * 100; // Percentage remaining (100% to 0%)
-
- // Update progress bar (shows remaining time, fills from left to right)
- var progressBar = $("#module-indicator-progress");
- if (progressBar.length > 0) {
- progressBar.css('width', progress + '%');
- }
-
- // Stop interval if timer is complete
- if (progress <= 0) {
- clearInterval(moduleProgressInterval);
- }
- }, 100); // Update every 100ms
-}
-
-// Function to stop progress bar animation
-function stopModuleProgressBar() {
- clearInterval(moduleProgressInterval);
- moduleClearStartTime = null;
- var progressBar = $("#module-indicator-progress");
- if (progressBar.length > 0) {
- progressBar.css('width', '100%');
- }
-}
-
-// Function to update module indicator icon
-function updateModuleIndicator() {
- var indicator = $("#module-indicator");
-
- // Check if there's a last displayed module and if it's currently hidden
- if (lastDisplayedModule) {
- var isCurrentlyVisible = false;
- var moduleIcon = '';
-
- if (lastDisplayedModule === 'idcard') {
- isCurrentlyVisible = $("#ped-interaction-id-card").is(":visible");
- moduleIcon = 'fas fa-id-card';
- } else if (lastDisplayedModule === 'vehicle') {
- isCurrentlyVisible = $("#vehicle-info").is(":visible");
- moduleIcon = 'fas fa-car';
- } else if (lastDisplayedModule === 'inventory') {
- isCurrentlyVisible = $("#ped-interaction-inventory").is(":visible");
- moduleIcon = 'fas fa-box';
- }
-
- // Show indicator only if module is hidden
- if (!isCurrentlyVisible) {
- if (indicator.length === 0) {
- // Create indicator if it doesn't exist
- $('body').append(`
-
-
-
- ${language.Press} TAB
-
-
-
- `);
- // Show the indicator after creation
- $("#module-indicator").fadeIn(200);
- } else {
- // Update existing indicator
- indicator.find('i').attr('class', moduleIcon + ' me-2');
- indicator.find('span').html(`${language.Press} TAB `);
- // Ensure progress bar container exists
- if (indicator.find('.module-indicator-progress-container').length === 0) {
- indicator.append(`
-
- `);
- }
- indicator.fadeIn(200);
- }
- } else {
- // Hide indicator if module is visible
- indicator.fadeOut(200);
- stopModuleProgressBar();
- }
- } else {
- // Hide indicator if no last displayed module
- indicator.fadeOut(200);
- }
-}
-
-// Function to re-display last shown module (called from Lua client)
-function redisplayLastModule() {
- // Toggle visibility: hide if visible, show if hidden
- if (lastDisplayedModule) {
- var isCurrentlyVisible = false;
-
- if (lastDisplayedModule === 'idcard' && $("#ped-interaction-id-card").is(":visible")) {
- isCurrentlyVisible = true;
- } else if (lastDisplayedModule === 'vehicle' && $("#vehicle-info").is(":visible")) {
- isCurrentlyVisible = true;
- } else if (lastDisplayedModule === 'inventory' && $("#ped-interaction-inventory").is(":visible")) {
- isCurrentlyVisible = true;
- }
-
- if (isCurrentlyVisible) {
- // Hide the module and clear timeout
- if (lastDisplayedModule === 'idcard') {
- clearTimeout(idCardTimeout);
- $("#ped-interaction-id-card").hide();
- } else if (lastDisplayedModule === 'vehicle') {
- clearTimeout(vehicleInfoTimeout);
- $("#vehicle-info").hide();
- } else if (lastDisplayedModule === 'inventory') {
- clearTimeout(inventoryTimeout);
- $("#ped-interaction-inventory").hide();
- }
- updateModuleIndicator();
- scheduleModuleClearIfHidden();
- } else {
- // Show the module if currently hidden
- // Clear the module clear timeout since we're showing it
- clearTimeout(moduleClearTimeout);
- stopModuleProgressBar();
- if (lastDisplayedModule === 'idcard' && lastIdCardData) {
- DisplayPedIdCard(true, lastIdCardData.personaldata, lastIdCardData.showdatabasecheck, idCardDbCheckCompleted);
- } else if (lastDisplayedModule === 'vehicle' && lastVehicleData) {
- DisplayVehicleInfo(true, lastVehicleData.vehicleData, lastVehicleData.DisableTaxAndMOT, vehicleDbCheckCompleted);
- } else if (lastDisplayedModule === 'inventory' && lastInventoryData) {
- DisplayPedInventory(true, lastInventoryData.itemList);
- }
- updateModuleIndicator();
- }
- }
-}
-
-// NPC Backup Request Radial Menu
-var listener = false;
-function setupButton(buttonId, iconClass, instructionText) {
- const button = document.getElementById(buttonId);
- $(`#${buttonId}`).html(` `);
-
- button.addEventListener('mouseenter', () => PlayNUISound('generic-sounds', "rollover", 0.5));
- button.addEventListener('mouseover', () => {
- document.getElementById('instruction-text').style.display = 'block';
- $("#instruction-text").html(`${instructionText}
`);
- });
- button.addEventListener('mouseout', () => document.getElementById('instruction-text').style.display = 'none');
-}
-
-function setupRadialMenu() {
- if (!listener) {
- listener = true;
-
- /*
- TO ADD NEW BACKUP, SIMPLY ADD YOUR BACKUP TYPE TO THE BUTTONS ARRAY BELOW AND CHANGE THE VALUES!
- MAKE SURE TO CREATE THE REQUIRED FUNCTION AND ADD THE CSS CODE IN STYLES.CSS!
- */
-
- // INSTRUCTION
- // const instructionText = document.getElementById('instruction-text');
- const buttons = [
- // THIS ALWAYS NEEDS TO BE THE FIRST ITEM IN THIS ARRAY!
- { id: 'middle-x', iconClass: '', instruction: language.ExitRadialMenuInstruction, hoverColour: '', function: 'ToggleRadialMenu(false)' },
- //
- { id: 'police-transport', iconClass: language.RequestPoliceTransportIcon, instruction: language.RequestPoliceTransportInstruction, hoverColour: '#0057b9', function: 'RequestOrCancelPoliceTransport()' },
- { id: 'ambulance-request', iconClass: language.RequestAmbulanceIcon, instruction: language.RequestAmbulanceInstruction, hoverColour: '#ff0000', function: 'RequestOrCancelAmbulance()' },
- { id: 'tow-request', iconClass: language.RequestTowIcon, instruction: language.RequestTowInstruction, hoverColour: '#782323', function: 'RequestOrCancelTow()' },
- { id: 'taxi-request', iconClass: language.RequestTaxiIcon, instruction: language.RequestTaxiInstruction, hoverColour: '#FF9A18', function: 'RequestOrCancelTaxi()' },
- { id: 'road-service-request', iconClass: language.RequestRoadServiceIcon, instruction: language.RequestRoadServiceInstruction, hoverColour: '#ffbf00', function: 'RequestOrCancelRoadService()' },
- { id: 'coroner-request', iconClass: language.RequestCoronerIcon, instruction: language.RequestCoronerInstruction, hoverColour: '#3D3D3D', function: 'RequestOrCancelCoroner()' },
- { id: 'animal-rescue-request', iconClass: language.RequestAnimalRescueIcon, instruction: language.RequestAnimalRescueInstruction, hoverColour: '#9bde00', function: 'RequestOrCancelAnimalRescue()' },
- { id: 'mechanic-request', iconClass: language.RequestMechanicIcon, instruction: language.RequestMechanicInstruction, hoverColour: '#3D3D3D', function: 'RequestOrCancelMechanic()' },
- { id: 'fire-request', iconClass: language.RequestFireIcon, instruction: language.RequestFireInstruction, hoverColour: '#3D3D3D', function: 'RequestOrCancelFire()' }
- ];
-
- $('#circle-menu').html(`
-
+let resourceName=null,language=null,commands=null,firstnames={},lastnames={},isDisplayingPreCalloutInterface=!1,isDisplayingCalloutInterface=!1,isDragMode=!1,isDragging=!1,dragElement=null,dragOffset={x:0,y:0},isLayoutMode=!1,layoutElements={},visibleLayoutElements=new Set,originalStyles=new Map,layoutBoundaries={left:20,top:20,right:20,bottom:20},snapGrid={enabled:!0,size:10},collisionDetection={enabled:!0},dimensionValidation={enabled:!0};window.addEventListener("message",e=>{let t=e.data;if("playSound"==t.transactionType&&PlayNUISound(t.transactionFolder,t.transactionFile,t.transactionVolume),"init"==t.type&&("undefined"!=typeof $?(resourceName=t.resourcename,language=t.language,commands=t.commands,firstnames=t.firstnames,lastnames=t.lastnames,$.post(`https://${resourceName}/initComplete`,JSON.stringify({complete:!0}))):console.log("Script is still loading...")),"togglecalloutinfo"==t.type&&toggleCalloutInfo(),"toggleUILayoutMode"==t.type&&(console.log("Received toggleUILayoutMode message from Lua"),toggleUILayoutMode()),"emergencyUICleanup"==t.type&&(console.log("Received emergencyUICleanup message from Lua"),emergencyUICleanup()),"ersselectionmenu"==t.type){var a,n,i,o=t.display;ToggleERSSelectionMenu(o,t.permissions)}if("radialmenu"==t.type){var o=t.display;ToggleRadialMenu(o)}if("pursuitradialmenu"==t.type){var o=t.display;TogglePursuitRadialMenu(o)}if("pursuitmode"==t.type){var s,l,o=t.display,r=t.displayhotkeyhint;TogglePursuitModeUI(o,r,t.zoomhotkey,t.backuphotkey)}if("dualsteeringmode"==t.type){var o=t.display;ToggleDualSteeringMode(o)}if("hotkeyhintprompt"==t.type){var o=t.display,c=t.hotkeys,d=t.time;ToggleHotKeyHintPrompt(o,c,language,d)}if("dispatchmessage"==t.type){var u,o=t.display,c=t.hotkeys,g=t.messagetype,p=t.calloutdata,b=t.message,d=t.time;AddMessageToDispatchQueue(o,c,g,p,d,b,t.toggle)}if("calloutprompt"==t.type){var m,o=t.display,p=t.calloutdata,c=t.hotkeys,d=t.time;ToggleCalloutDisplayPrompt(o,c,language,d,p,t.serviceType)}if("calloutpreinterface"==t.type){var o=t.display,c=t.hotkeys,p=t.calloutdata;TogglePreCalloutInterface(o,c,p)}if("calloutinterface"==t.type){var h,y,o=t.display,c=t.hotkeys,f=t.pedCount,v=t.vehicleCount,x=t.objectCount,w=t.propCount,k=t.fireCount,C=t.smokeCount,p=t.calloutdata,I=t.pedOriginalCount,T=t.vehOriginalCount,S=t.objOriginalCount,P=t.propOriginalCount;ToggleCalloutInterface(o,c,f,v,x,w,k,C,p,I,T,S,P,t.fireOriginalCount,t.smokeOriginalCount)}if("unifiedprompt"==t.type){var o=t.display,E=t.promptType,R=t.hotkey,b=t.message,d=t.time;DisplayUnifiedPrompt(o,E,R,b,d)}if("interactionmodule"==t.type){var N,A,o=t.display;DisplayPedInteractionModule(o,t.ispeddeadordying,t.service)}if("idcardprompt"==t.type){var M,_,o=t.display;DisplayPedIdCard(o,t.pedpersonaldata,t.showdatabasecheck)}if("inventoryprompt"==t.type){var q,o=t.display;DisplayPedInventory(o,t.itemlist)}if("vehicleinfoprompt"==t.type){var D,O,o=t.display;DisplayVehicleInfo(o,t.vehicleData,t.DisableTaxAndMOT)}if("togglequestionsmodule"==t.type){var L,o=t.display;ToggleQuestionsModule(o,t.questions)}if("updateanswers"==t.type){var B,o=t.display;UpdateAnswers(o,t.answers)}if("addorremovewaypoint"==t.type&&AddWaypoint(t.addwaypoint),"updatewaypoint"==t.type){var U,j,F,G=t.scaleX;UpdateWaypointPosition(G,t.scaleY,t.distanceText)}if("areyousure"==t.type){var o=t.display;DisplayAreYouSurePopup(o)}if("gearmenu"==t.type){var W,o=t.display;DisplayGearMenu(o,t.locationdata)}if("updatezonechange"==t.type){UpdateZoneChangeUI(t.lastZone,t.currentZone)}"updatewaypoints"===t.type&&updateWaypoints(t)});var unifiedPromptTimeout,idCardTimeout,dbCheckTimeout,vehicleInfoTimeout,vehicleDbCheckTimeout,inventoryTimeout,zoneChangeTimeout=null;let zoneChangeQueue=[],isAnimating=!1;function UpdateZoneChangeUI(e,t){zoneChangeQueue.push({oldZone:e,newZone:t}),isAnimating||processNextZoneChange()}function processNextZoneChange(){if(0===zoneChangeQueue.length){isAnimating=!1;return}isAnimating=!0;let{oldZone:e,newZone:t}=zoneChangeQueue.shift(),a=document.getElementById("zone-change-ui");if(!a){processNextZoneChange();return}let n=a.querySelector(".old-zone"),i=a.querySelector(".new-zone");if(!n||!i){processNextZoneChange();return}zoneChangeTimeout&&clearTimeout(zoneChangeTimeout),a.classList.remove("show"),i.classList.remove("show"),n.textContent=e||"N/A",i.textContent=t||"N/A",a.offsetWidth,a.classList.add("show"),i.classList.add("show"),zoneChangeTimeout=setTimeout(()=>{a.classList.remove("show"),i.classList.remove("show"),setTimeout(processNextZoneChange,500)},4e3)}let escapeEventListenerAdded=!1;function DisplayAreYouSurePopup(e){if(e){$("#are-you-sure-modal").remove();let t=` ${language.CompletingCalloutCannotBeUndone}
`;$("body").append(t),$("#are-you-sure-modal").modal({backdrop:"static",keyboard:!1}),$("#are-you-sure-modal").modal("show"),$("#are-you-sure-modal").on("shown.bs.modal",function(){escapeEventListenerAdded||($(document).on("keydown",function(e){"Escape"===e.key&&($("#are-you-sure-modal").modal("hide"),handleNoClick(),e.stopPropagation())}),escapeEventListenerAdded=!0)}).on("hidden.bs.modal",function(){$(document).off("keydown"),escapeEventListenerAdded=!1})}else $("#are-you-sure-modal").remove()}function handleNoClick(){$.post(`https://${resourceName}/AreYouSure`,JSON.stringify({areyousure:!1})),$("#are-you-sure-modal").modal("hide")}function handleYesClick(){$.post(`https://${resourceName}/AreYouSure`,JSON.stringify({areyousure:!0})),$("#are-you-sure-modal").modal("hide")}function DisplayPedInteractionModule(e,t,a){if(e){if(DisplayUnifiedPrompt(!1),t)$("#ped-interaction-module").empty(),$("#ped-interaction-module").show(),$("#ped-interaction-module").append(` ${language.InteractionOptions} ${[{id:"identify",label:language.IdentifyDeadPed,explanation:language.IdentifyDeadPedExplanation},{id:"drag",label:language.DragPed,explanation:language.DragPedExplanation},{id:"massivebleeding",label:language.CheckMassiveBleeding,explanation:language.CheckMassiveExplanation},{id:"airway",label:language.CheckAirway,explanation:language.CheckAirwayExplanation},{id:"breathing",label:language.CheckBreathing,explanation:language.CheckBreathingExplanation},{id:"circulation",label:language.CheckCirculation,explanation:language.CheckCirculationExplanation},{id:"hypothermia",label:language.CheckHypothermia,explanation:language.CheckHypothermiaExplanation},{id:"cpr",label:language.PerformCPR,explanation:language.PerformCPRExplanation},{id:"putonstretcher",label:language.PutOnStretcher,explanation:language.PutOnStretcherExplanation},{id:"takeoffstretcher",label:language.TakeOffStretcher,explanation:language.TakeOffStretcherExplanation},{id:"bodybag",label:language.PutInBodyBag,explanation:language.PutInBodyBagExplanation}].map(e=>`
${e.label}
${e.explanation}
`).join("")}
${language.ExitInteraction}
`),applySavedPosition("ped-interaction-module"),["identify","drag","massivebleeding","airway","breathing","circulation","hypothermia","cpr","putonstretcher","takeoffstretcher","bodybag","exit"].forEach(e=>addSoundOnHoverEventListener(`p-btn-${e}`));else{$("#ped-interaction-module").empty(),$("#ped-interaction-module").show();var n={police:[{id:"greet",label:language.Greet,explanation:language.GreetExplanation},{id:"id",label:language.AskForId,explanation:language.AskForIdExplanation},{id:"questioning",label:language.Question,explanation:language.QuestionExplanation},{id:"breathalyze",label:language.Breathalyze,explanation:language.BreathalyzeExplanation},{id:"drugtest",label:language.DrugTest,explanation:language.DrugTestExplanation},{id:"warn",label:language.Warn,explanation:language.WarnExplanation},{id:"fine",label:language.Fine,explanation:language.FineExplanation},{id:"grab",label:language.Grab,explanation:language.GrabExplanation},{id:"getout",label:language.GetOut,explanation:language.GetOutExplanation},{id:"follow",label:language.AskToFollow,explanation:language.AskToFollowExplanation},{id:"wait",label:language.AskToWait,explanation:language.AskToWaitExplanation},{id:"handsup",label:language.HandsUp,explanation:language.HandsUpExplanation},{id:"search",label:language.Search,explanation:language.SearchExplanation},{id:"cuff",label:language.Cuff,explanation:language.CuffExplanation},{id:"putinvehicle",label:language.PutInVehicle,explanation:language.PutInVehicleExplanation}],ambulance:[{id:"greet",label:language.Greet,explanation:language.GreetExplanation},{id:"questioning",label:language.Question,explanation:language.QuestionExplanation},{id:"breathalyze",label:language.Breathalyze,explanation:language.BreathalyzeExplanation},{id:"drugtest",label:language.DrugTest,explanation:language.DrugTestExplanation},{id:"getout",label:language.GetOut,explanation:language.GetOutExplanation},{id:"follow",label:language.AskToFollow,explanation:language.AskToFollowExplanation},{id:"wait",label:language.AskToWait,explanation:language.AskToWaitExplanation},{id:"putinvehicle",label:language.PutInVehicle,explanation:language.PutInVehicleExplanation}],fire:[{id:"greet",label:language.Greet,explanation:language.GreetExplanation},{id:"questioning",label:language.Question,explanation:language.QuestionExplanation},{id:"breathalyze",label:language.Breathalyze,explanation:language.BreathalyzeExplanation},{id:"drugtest",label:language.DrugTest,explanation:language.DrugTestExplanation},{id:"getout",label:language.GetOut,explanation:language.GetOutExplanation},{id:"follow",label:language.AskToFollow,explanation:language.AskToFollowExplanation},{id:"wait",label:language.AskToWait,explanation:language.AskToWaitExplanation},{id:"putinvehicle",label:language.PutInVehicle,explanation:language.PutInVehicleExplanation}],tow:[{id:"greet",label:language.Greet,explanation:language.GreetExplanation},{id:"questioning",label:language.Question,explanation:language.QuestionExplanation},{id:"getout",label:language.GetOut,explanation:language.GetOutExplanation},{id:"follow",label:language.AskToFollow,explanation:language.AskToFollowExplanation},{id:"wait",label:language.AskToWait,explanation:language.AskToWaitExplanation},{id:"putinvehicle",label:language.PutInVehicle,explanation:language.PutInVehicleExplanation}]};$("#ped-interaction-module").append(` ${language.InteractionOptions} ${(n[a]||n.police).map(e=>`
${e.label}
${e.explanation}
`).join("")}
${language.StopInteraction} ${language.ExitInteraction} ${"police"===a?`${language.SendToCustody} `:""}
`);let i=n[a]||n.police,o=[...i.map(e=>e.id),"end","exit",..."police"===a?["custody"]:[]];o.forEach(e=>addSoundOnHoverEventListener(`p-btn-${e}`)),applySavedPosition("ped-interaction-module")}}else $("#ped-interaction-module").hide()}function PedInteraction(e){$.post(`https://${resourceName}/pedInteraction`,JSON.stringify({interactionType:e}))}function addSoundOnHoverEventListener(e){document.getElementById(e).addEventListener("mouseenter",function(){PlayNUISound("generic-sounds","rollover",.5)})}function DisplayUnifiedPrompt(e,t,a,n,i){if(e){$("#unified-prompt").show(),applySavedPosition("unified-prompt"),clearTimeout(unifiedPromptTimeout);let o={pedinteraction:{icon:"\uD83D\uDCAC",color:"text-warning",text:language.ToInteract,timeout:1500},injuredped:{icon:"\uD83E\uDE7A",color:"text-danger",text:language.ToPerformCPR,timeout:1500},impound:{icon:"\uD83D\uDE97",color:"text-danger",text:language.ToInteractImpound,timeout:1500},gear:{icon:"\uD83D\uDE97",color:"text-danger",text:language.ToInteractGear,timeout:1500},stretcher:{icon:"\uD83C\uDFE5",color:"text-info",text:language.ToUseStretcherVeh,timeout:1500},objectcleanup:{icon:"\uD83E\uDDF9",color:"text-success",text:language.ToCleanupObject,timeout:1500},spikesvehicle:{icon:"\uD83D\uDCA2",color:"text-warning",text:n||"",timeout:i||1500}},s=o[t]||o.pedinteraction;$("#unified-prompt").html(`
+ ${s.icon} ${language.Press} ${a} ${s.text}
+ `),unifiedPromptTimeout=setTimeout(function(){$("#unified-prompt").hide()},s.timeout)}else $("#unified-prompt").hide()}function DisplayPedIdCard(e,t,a){if(e){$("#vehicle-info").hide(),$("#ped-interaction-inventory").hide(),clearTimeout(idCardTimeout),clearTimeout(dbCheckTimeout),$("#ped-interaction-id-card").empty();var n=t.ProfilePicture||"N/A",i=t.FirstName||"N/A",o=t.LastName||"N/A",s=t.DOB||"N/A",l=t.Gender||"N/A",r=t.Email||"N/A",c=t.PhoneNumber||"N/A",d=t.Country||"N/A",u=t.State||"N/A",g=t.City||"N/A",p=t.PostalCode||"N/A",b=t.Address||"N/A";t.AddressType;var m=t.Nationality||"N/A",h=t.FlagsOrMarkers,y=t.License_Car||"N/A",f=t.License_Car_Colour||"text-light",v=t.License_Car_Icon||"fas fa-car",x=t.License_Bike||"N/A",w=t.License_Bike_Colour||"text-light",k=t.License_Bike_Icon||"fas fa-bicycle",C=t.License_Boat||"N/A",I=t.License_Boat_Colour||"text-light",T=t.License_Boat_Icon||"fas fa-ship",S=t.License_Truck||"N/A",P=t.License_Truck_Colour||"text-light",E=t.License_Truck_Icon||"fas fa-truck",R=t.License_Pilot||"N/A",N=t.License_Pilot_Colour||"text-light",A=t.License_Pilot_Icon||"fas fa-plane";$("#ped-interaction-id-card").append(` ${language.FullName} ${i} ${o} ${language.DOB} ${s} `),$("#ped-interaction-id-card").show(),applySavedPosition("ped-interaction-id-card"),a&&($("#ped-interaction-id-card").append(` Loading...
${language.RunningDatabaseCheck}
`),dbCheckTimeout=setTimeout(function(){$("#initial-check").remove(),$("#database-check").html(` ${i} ${o}
(${s})
${language.Nationality} ${m} ${language.Gender} ${l} ${language.Address} ${b}, ${g}, ${u} ${p} (${d}) ${language.Email} ${r} | ${language.PhoneNumber} ${c} ${language.Licenses} ${y} ${x} ${C} ${S} ${R}
${h&&Object.keys(h).some(e=>h[e])?`
${language.FlagsOrMarkers} ${h.armed_and_dangerous?` ${language.armed_and_dangerous} `:""} ${h.assault?` ${language.assault} `:""} ${h.burglary?` ${language.burglary} `:""} ${h.drug_related?` ${language.drug_related} `:""} ${h.gang_affiliation?` ${language.gang_affiliation} `:""} ${h.homicide?` ${language.homicide} `:""} ${h.kidnapping?` ${language.kidnapping} `:""} ${h.mental_health_issues?` ${language.mental_health_issues} `:""} ${h.sex_offense?` ${language.sex_offense} `:""} ${h.terrorism?` ${language.terrorism} `:""} ${h.theft?` ${language.theft} `:""} ${h.traffic_violation?` ${language.traffic_violation} `:""} ${h.wanted_person?` ${language.wanted_person} `:""} ${h.other?` ${language.other} `:""} ${h.active_warrant?` ${language.active_warrant} `:""}
`:""}
`)},3e3)),idCardTimeout=setTimeout(function(){$("#ped-interaction-id-card").hide()},15e3)}else $("#ped-interaction-id-card").hide()}function DisplayVehicleInfo(e,t,a){if(e){$("#ped-interaction-id-card").hide(),$("#ped-interaction-inventory").hide(),clearTimeout(vehicleInfoTimeout),clearTimeout(vehicleDbCheckTimeout),$("#vehicle-info").empty();var n={vehNetId:t.vehNetId,license_plate:t.license_plate,model:t.model,model_hash:t.model_hash,vehicle_class:t.vehicle_class,vehicle_class_from_name:t.vehicle_class_from_name,color:t.color,color_secondary:t.color_secondary,build_year:t.build_year,tax:t.tax,mot:t.mot,insurance:t.insurance,stolen:t.stolen,bolo:t.bolo,bolo_description:t.bolo_description,owner_name:t.owner_name};$("#vehicle-info").append(` ${language.VehiclePlate} ${n.license_plate} ${language.VehicleModel} ${n.model} `),$("#vehicle-info").append(` Loading...
${language.RunningDatabaseCheck}
`),$("#vehicle-info").show(),applySavedPosition("vehicle-info"),vehicleDbCheckTimeout=setTimeout(function(){$("#vehicle-info-database-check").html(` `)},5e3),vehicleInfoTimeout=setTimeout(function(){$("#vehicle-info").hide()},15e3)}else $("#vehicle-info").hide()}function DisplayPedInventory(e,t){e?($("#ped-interaction-id-card").hide(),$("#vehicle-info").hide(),clearTimeout(inventoryTimeout),$("#ped-interaction-inventory").empty(),$("#ped-interaction-inventory").append(` ${language.Inventory} `),$.each(t,function(e,t){var a,n=` ${t.name} `;$("#inventory-table-body").append(n)}),$("#ped-interaction-inventory").show(),applySavedPosition("ped-interaction-inventory"),inventoryTimeout=setTimeout(function(){$("#ped-interaction-inventory").hide()},15e3)):$("#ped-interaction-inventory").hide()}var listener=!1;function setupButton(e,t,a){let n=document.getElementById(e);$(`#${e}`).html(` `),n.addEventListener("mouseenter",()=>PlayNUISound("generic-sounds","rollover",.5)),n.addEventListener("mouseover",()=>{document.getElementById("instruction-text").style.display="block",$("#instruction-text").html(`${a}
`)}),n.addEventListener("mouseout",()=>document.getElementById("instruction-text").style.display="none")}function setupRadialMenu(){if(!listener){listener=!0;let e=[{id:"middle-x",iconClass:"",instruction:language.ExitRadialMenuInstruction,hoverColour:"",function:"ToggleRadialMenu(false)"},{id:"police-transport",iconClass:language.RequestPoliceTransportIcon,instruction:language.RequestPoliceTransportInstruction,hoverColour:"#0057b9",function:"RequestOrCancelPoliceTransport()"},{id:"ambulance-request",iconClass:language.RequestAmbulanceIcon,instruction:language.RequestAmbulanceInstruction,hoverColour:"#ff0000",function:"RequestOrCancelAmbulance()"},{id:"tow-request",iconClass:language.RequestTowIcon,instruction:language.RequestTowInstruction,hoverColour:"#782323",function:"RequestOrCancelTow()"},{id:"taxi-request",iconClass:language.RequestTaxiIcon,instruction:language.RequestTaxiInstruction,hoverColour:"#FF9A18",function:"RequestOrCancelTaxi()"},{id:"road-service-request",iconClass:language.RequestRoadServiceIcon,instruction:language.RequestRoadServiceInstruction,hoverColour:"#ffbf00",function:"RequestOrCancelRoadService()"},{id:"coroner-request",iconClass:language.RequestCoronerIcon,instruction:language.RequestCoronerInstruction,hoverColour:"#3D3D3D",function:"RequestOrCancelCoroner()"},{id:"animal-rescue-request",iconClass:language.RequestAnimalRescueIcon,instruction:language.RequestAnimalRescueInstruction,hoverColour:"#9bde00",function:"RequestOrCancelAnimalRescue()"},{id:"mechanic-request",iconClass:language.RequestMechanicIcon,instruction:language.RequestMechanicInstruction,hoverColour:"#3D3D3D",function:"RequestOrCancelMechanic()"},{id:"fire-request",iconClass:language.RequestFireIcon,instruction:language.RequestFireInstruction,hoverColour:"#3D3D3D",function:"RequestOrCancelFire()"}];$("#circle-menu").html(`
+
- ${buttons.slice(1).map(button => ` `).join('')}
+ ${e.slice(1).map(e=>` `).join("")}
- `)
-
- buttons.forEach(({ id, iconClass, instruction }) => setupButton(id, iconClass, instruction));
- }
-}
-
-function ToggleRadialMenu(display) {
- setupRadialMenu();
-
- if (display) {
- // Add escape key event listener
- document.addEventListener('keyup', handleRadialMenuEscape);
-
- const instructionTitle = document.getElementById('instruction-title');
- instructionTitle.style.display = 'block';
- $("#instruction-title").html(`${language.RadialMenuInstructionTitle}
`);
- $("#circle-menu").show();
-
- // Apply the blur overlay
- $("body").append("
");
-
- } else {
- // Remove escape key event listener
- document.removeEventListener('keyup', handleRadialMenuEscape);
-
- PlayNUISound('generic-sounds', "radialclose", 0.5);
-
- // Hide all instruction elements
- const instructionTitle = document.getElementById('instruction-title');
- const instructionText = document.getElementById('instruction-text');
-
- if (instructionTitle) {
- instructionTitle.style.display = 'none';
- }
- if (instructionText) {
- instructionText.style.display = 'none';
- }
-
- $("#circle-menu").hide();
- $.post(`https://${resourceName}/closeRadialMenu`, JSON.stringify({}));
-
- // Remove the blur overlay
- $(".blur-overlay").remove();
- }
-}
-
-function handleRadialMenuEscape(event) {
- if (event.key === 'Escape') {
- ToggleRadialMenu(false);
- }
-}
-
-function RequestOrCancelPoliceTransport() {
- ToggleRadialMenu(false)
- $.post(`https://${resourceName}/requestOrCancelPoliceTransport`, JSON.stringify({}))
-}
-
-function RequestOrCancelAmbulance() {
- ToggleRadialMenu(false)
- $.post(`https://${resourceName}/requestOrCancelAmbulance`, JSON.stringify({}))
-}
-
-function RequestOrCancelTow() {
- ToggleRadialMenu(false)
- $.post(`https://${resourceName}/requestOrCancelTow`, JSON.stringify({}))
-}
-
-function RequestOrCancelTaxi() {
- ToggleRadialMenu(false)
- $.post(`https://${resourceName}/requestOrCancelTaxi`, JSON.stringify({}))
-}
-
-function RequestOrCancelRoadService() {
- ToggleRadialMenu(false)
- $.post(`https://${resourceName}/requestOrCancelRoadService`, JSON.stringify({}))
-}
-
-function RequestOrCancelCoroner() {
- ToggleRadialMenu(false)
- $.post(`https://${resourceName}/requestOrCancelCoroner`, JSON.stringify({}))
-}
-
-function RequestOrCancelAnimalRescue() {
- ToggleRadialMenu(false)
- $.post(`https://${resourceName}/requestOrCancelAnimalRescue`, JSON.stringify({}))
-}
-
-function RequestOrCancelMechanic() {
- ToggleRadialMenu(false)
- $.post(`https://${resourceName}/requestOrCancelMechanic`, JSON.stringify({}))
-}
-
-function RequestOrCancelFire() {
- ToggleRadialMenu(false)
- $.post(`https://${resourceName}/requestOrCancelFire`, JSON.stringify({}))
-}
-
-// Pursuit Mode UI
-
-function TogglePursuitModeUI(display, displayhotkeyhint, zoomhotkey, backuphotkey) {
- $("#pursuit-mode-ui").toggle(display);
- if (display) {
-
- // MINIFY
- $("#pursuit-mode-ui").html(` ${language.ActivePursuit}
${displayhotkeyhint ? `
${zoomhotkey} (${language.PursuitHotkeyFocus}) | ${backuphotkey} (${language.PursuitHotkeyBackup})
` : ''}
`);
-
- // HTML
- // $("#pursuit-mode-ui").html(`
- //
- //
- //
- //
- // ${language.ActivePursuit}
- //
- //
- //
- // ${displayhotkeyhint ? `
- //
- // ${zoomhotkey} (${language.PursuitHotkeyFocus}) | ${backuphotkey} (${language.PursuitHotkeyBackup})
- //
- // ` : ''}
- //
- //
- //
- // `);
-
- } else {
- $("#pursuit-mode-ui").hide();
- }
-}
-
-//Pursuit Radial Menu
-var pursuitRadialMenuListener = false;
-function setupPursuitRadialMenuButton(buttonId, iconClass, instructionText) {
- const button = document.getElementById(buttonId);
- $(`#${buttonId}`).html(` `);
-
- // Use mouseenter instead of mouseover to prevent event bubbling
- button.addEventListener('mouseenter', () => {
- PlayNUISound('generic-sounds', "rollover", 0.5);
- document.getElementById('pursuit-instruction-text').style.display = 'block';
- $("#pursuit-instruction-text").html(`${instructionText}
`);
- });
-
- // Use mouseleave instead of mouseout to prevent event bubbling
- button.addEventListener('mouseleave', () => {
- document.getElementById('pursuit-instruction-text').style.display = 'none';
- });
-}
-
-function setupPursuitRadialMenu() {
- if (!pursuitRadialMenuListener) {
- pursuitRadialMenuListener = true;
-
- // INSTRUCTION
- // const instructionText = document.getElementById('pursuit-instruction-text');
- const buttons = [
- // THIS ALWAYS NEEDS TO BE THE FIRST ITEM IN THIS ARRAY!
- { id: 'pursuit-middle-x', iconClass: '', instruction: language.ExitRadialMenuInstruction, hoverColour: '', function: 'TogglePursuitRadialMenu(false)' },
- //
- { id: 'pursuit-backup-light', iconClass: language.RequestLightBackupIcon, instruction: language.RequestLightBackupInstruction, hoverColour: '#0080f8', function: "RequestPursuitBackup('light')" },
- { id: 'pursuit-backup-medium', iconClass: language.RequestMediumBackupIcon, instruction: language.RequestMediumBackupInstruction, hoverColour: '#014b8f', function: "RequestPursuitBackup('medium')" },
- { id: 'pursuit-backup-heavy', iconClass: language.RequestHeavyBackupIcon, instruction: language.RequestHeavyBackupInstruction, hoverColour: '#001e39', function: "RequestPursuitBackup('heavy')" },
- { id: 'pursuit-backup-air', iconClass: language.RequestAirBackupIcon, instruction: language.RequestAirBackupInstruction, hoverColour: '#00a2dd', function: "RequestPursuitBackup('air')" },
- { id: 'pursuit-backup-army', iconClass: language.RequestArmyBackupIcon, instruction: language.RequestArmyBackupInstruction, hoverColour: '#647b32', function: "RequestPursuitBackup('army')" },
- ];
-
- $('#pursuit-radial-menu').html(`
-
+ `),e.forEach(({id:e,iconClass:t,instruction:a})=>setupButton(e,t,a))}}function ToggleRadialMenu(e){if(setupRadialMenu(),e){document.addEventListener("keyup",handleRadialMenuEscape);let t=document.getElementById("instruction-title");t.style.display="block",$("#instruction-title").html(`${language.RadialMenuInstructionTitle}
`),$("#circle-menu").show(),$("body").append("
")}else{document.removeEventListener("keyup",handleRadialMenuEscape),PlayNUISound("generic-sounds","radialclose",.5);let a=document.getElementById("instruction-title"),n=document.getElementById("instruction-text");a&&(a.style.display="none"),n&&(n.style.display="none"),$("#circle-menu").hide(),$.post(`https://${resourceName}/closeRadialMenu`,JSON.stringify({})),$(".blur-overlay").remove()}}function handleRadialMenuEscape(e){"Escape"===e.key&&ToggleRadialMenu(!1)}function RequestOrCancelPoliceTransport(){ToggleRadialMenu(!1),$.post(`https://${resourceName}/requestOrCancelPoliceTransport`,JSON.stringify({}))}function RequestOrCancelAmbulance(){ToggleRadialMenu(!1),$.post(`https://${resourceName}/requestOrCancelAmbulance`,JSON.stringify({}))}function RequestOrCancelTow(){ToggleRadialMenu(!1),$.post(`https://${resourceName}/requestOrCancelTow`,JSON.stringify({}))}function RequestOrCancelTaxi(){ToggleRadialMenu(!1),$.post(`https://${resourceName}/requestOrCancelTaxi`,JSON.stringify({}))}function RequestOrCancelRoadService(){ToggleRadialMenu(!1),$.post(`https://${resourceName}/requestOrCancelRoadService`,JSON.stringify({}))}function RequestOrCancelCoroner(){ToggleRadialMenu(!1),$.post(`https://${resourceName}/requestOrCancelCoroner`,JSON.stringify({}))}function RequestOrCancelAnimalRescue(){ToggleRadialMenu(!1),$.post(`https://${resourceName}/requestOrCancelAnimalRescue`,JSON.stringify({}))}function RequestOrCancelMechanic(){ToggleRadialMenu(!1),$.post(`https://${resourceName}/requestOrCancelMechanic`,JSON.stringify({}))}function RequestOrCancelFire(){ToggleRadialMenu(!1),$.post(`https://${resourceName}/requestOrCancelFire`,JSON.stringify({}))}function TogglePursuitModeUI(e,t,a,n){$("#pursuit-mode-ui").toggle(e),e?$("#pursuit-mode-ui").html(` ${language.ActivePursuit}
${t?`
${a} (${language.PursuitHotkeyFocus}) | ${n} (${language.PursuitHotkeyBackup})
`:""}
`):$("#pursuit-mode-ui").hide()}var pursuitRadialMenuListener=!1;function setupPursuitRadialMenuButton(e,t,a){let n=document.getElementById(e);$(`#${e}`).html(` `),n.addEventListener("mouseenter",()=>{PlayNUISound("generic-sounds","rollover",.5),document.getElementById("pursuit-instruction-text").style.display="block",$("#pursuit-instruction-text").html(`${a}
`)}),n.addEventListener("mouseleave",()=>{document.getElementById("pursuit-instruction-text").style.display="none"})}function setupPursuitRadialMenu(){if(!pursuitRadialMenuListener){pursuitRadialMenuListener=!0;let e=[{id:"pursuit-middle-x",iconClass:"",instruction:language.ExitRadialMenuInstruction,hoverColour:"",function:"TogglePursuitRadialMenu(false)"},{id:"pursuit-backup-light",iconClass:language.RequestLightBackupIcon,instruction:language.RequestLightBackupInstruction,hoverColour:"#0080f8",function:"RequestPursuitBackup('light')"},{id:"pursuit-backup-medium",iconClass:language.RequestMediumBackupIcon,instruction:language.RequestMediumBackupInstruction,hoverColour:"#014b8f",function:"RequestPursuitBackup('medium')"},{id:"pursuit-backup-heavy",iconClass:language.RequestHeavyBackupIcon,instruction:language.RequestHeavyBackupInstruction,hoverColour:"#001e39",function:"RequestPursuitBackup('heavy')"},{id:"pursuit-backup-air",iconClass:language.RequestAirBackupIcon,instruction:language.RequestAirBackupInstruction,hoverColour:"#00a2dd",function:"RequestPursuitBackup('air')"},{id:"pursuit-backup-army",iconClass:language.RequestArmyBackupIcon,instruction:language.RequestArmyBackupInstruction,hoverColour:"#647b32",function:"RequestPursuitBackup('army')"},];$("#pursuit-radial-menu").html(`
+
- ${buttons.slice(1).map(button => ` `).join('')}
+ ${e.slice(1).map(e=>` `).join("")}
- `)
-
- buttons.forEach(({ id, iconClass, instruction }) => setupPursuitRadialMenuButton(id, iconClass, instruction));
- }
-}
-
-function TogglePursuitRadialMenu(display) {
- setupPursuitRadialMenu();
-
- if (display) {
- // Add escape key event listener
- document.addEventListener('keyup', handlePursuitRadialMenuEscape);
-
- const instructionTitle = document.getElementById('pursuit-instruction-title');
- instructionTitle.style.display = 'block';
- $("#pursuit-instruction-title").html(`${language.PursuitRadialMenuInstructionTitle}
`);
- $("#pursuit-radial-menu").show();
-
- // Apply the blur overlay
- $("body").append("
");
-
- } else {
- // Remove escape key event listener
- document.removeEventListener('keyup', handlePursuitRadialMenuEscape);
-
- PlayNUISound('generic-sounds', "radialclose", 0.5);
- const instructionTitle = document.getElementById('pursuit-instruction-title');
- if (instructionTitle) {
- instructionTitle.style.display = 'none';
- }
- const instructionText = document.getElementById('pursuit-instruction-text');
- if (instructionText) {
- instructionText.style.display = 'none';
- }
-
- $("#pursuit-radial-menu").hide();
- $.post(`https://${resourceName}/closePursuitRadialMenu`, JSON.stringify({}));
-
- // Remove the blur overlay
- $(".blur-overlay").remove();
- }
-}
-
-function handlePursuitRadialMenuEscape(event) {
- if (event.key === 'Escape') {
- TogglePursuitRadialMenu(false);
- }
-}
-
-function RequestPursuitBackup(unitType) {
- TogglePursuitRadialMenu(false)
- $.post(`https://${resourceName}/requestPursuitBackup`, JSON.stringify({unitType: unitType}));
-}
-
-// DISPATCH
-
-var isDispatchQueueProcessing = false;
-var dispatchMessages = [];
-
-function AddMessageToDispatchQueue(display, hotkeys, messagetype, calloutdata, timeInMS, message, toggle) {
- dispatchMessages.push({ display: display, hotkeys: hotkeys, messagetype: messagetype, calloutdata: calloutdata, timeInMS: timeInMS, message: message, toggle: toggle });
- if (!isDispatchQueueProcessing) {
- ProcessDispatchQueue();
- }
-}
-
-function ProcessDispatchQueue() {
- if (dispatchMessages.length > 0) {
- isDispatchQueueProcessing = true;
-
- var message = dispatchMessages[0]; // Get the first message from the queue without removing it
-
- DisplayDispatchMessage(message.display, message.hotkeys, message.messagetype, message.calloutdata, message.message, message.toggle);
-
- // Determine the timeout duration based on the message.toggle property
- var timeoutDuration = message.toggle ? message.timeInMS : 3000; // Use 3000ms if toggle is false
-
- // Set the countdown timer for the message
- StartCountdownTimer(timeoutDuration);
-
- setTimeout(function() {
- dispatchMessages.shift(); // Remove the first message from the queue
- ProcessDispatchQueue();
- }, timeoutDuration);
- } else {
- isDispatchQueueProcessing = false;
- $("#dispatch-message-prompt-container").hide(); // Hide the message prompt container if there are no more messages
- }
-}
-
-function getDispatchIcon(messagetype) {
- switch(messagetype) {
- case "response":
- return ' ';
- case "arrival":
- return ' ';
- case "detach":
- return ' ';
- case "shift":
- return ' ';
- case "ambulance":
- return ' ';
- case "police":
- return ' ';
- case "fire":
- return ' ';
- case "tow":
- return ' ';
- case "taxi":
- return ' ';
- default:
- return ' ';
- }
-}
-
-function DisplayDispatchMessage(display, hotkeys, messagetype, calloutdata, message, toggle) {
-
- if (!toggle) {
- $("#dispatch-message-prompt-container").empty().show().append(`
+ `),e.forEach(({id:e,iconClass:t,instruction:a})=>setupPursuitRadialMenuButton(e,t,a))}}function TogglePursuitRadialMenu(e){if(setupPursuitRadialMenu(),e){document.addEventListener("keyup",handlePursuitRadialMenuEscape);let t=document.getElementById("pursuit-instruction-title");t.style.display="block",$("#pursuit-instruction-title").html(`${language.PursuitRadialMenuInstructionTitle}
`),$("#pursuit-radial-menu").show(),$("body").append("
")}else{document.removeEventListener("keyup",handlePursuitRadialMenuEscape),PlayNUISound("generic-sounds","radialclose",.5);let a=document.getElementById("pursuit-instruction-title");a&&(a.style.display="none");let n=document.getElementById("pursuit-instruction-text");n&&(n.style.display="none"),$("#pursuit-radial-menu").hide(),$.post(`https://${resourceName}/closePursuitRadialMenu`,JSON.stringify({})),$(".blur-overlay").remove()}}function handlePursuitRadialMenuEscape(e){"Escape"===e.key&&TogglePursuitRadialMenu(!1)}function RequestPursuitBackup(e){TogglePursuitRadialMenu(!1),$.post(`https://${resourceName}/requestPursuitBackup`,JSON.stringify({unitType:e}))}var isDispatchQueueProcessing=!1,dispatchMessages=[];function AddMessageToDispatchQueue(e,t,a,n,i,o,s){dispatchMessages.push({display:e,hotkeys:t,messagetype:a,calloutdata:n,timeInMS:i,message:o,toggle:s}),isDispatchQueueProcessing||ProcessDispatchQueue()}function ProcessDispatchQueue(){if(dispatchMessages.length>0){isDispatchQueueProcessing=!0;var e=dispatchMessages[0];DisplayDispatchMessage(e.display,e.hotkeys,e.messagetype,e.calloutdata,e.message,e.toggle);var t=e.toggle?e.timeInMS:3e3;StartCountdownTimer(t),setTimeout(function(){dispatchMessages.shift(),ProcessDispatchQueue()},t)}else isDispatchQueueProcessing=!1,$("#dispatch-message-prompt-container").hide()}function DisplayDispatchMessage(e,t,a,n,i,o){if(!o){$("#dispatch-message-prompt-container").empty().show().append(`
${language.DispatchMessage}
- `);
- return;
- }
-
-
- if (messagetype == "response" || messagetype == "arrival") {
-
- if (messagetype == "response") {
- $.post(`https://${resourceName}/offerToTrackPlayer`, JSON.stringify({calloutdata: calloutdata}));
- }
-
- // HTML
- $("#dispatch-message-prompt-container").empty().show().append(`
-
-
-
- ${calloutdata.CalloutName ? `
-
- ${calloutdata.CalloutName}
-
- ` : ''}
-
- ${message}
- ${calloutdata.Description ? `
- ${calloutdata.Description}
- ` : ''}
-
-
- ${language.Caller}
- ${calloutdata.FirstName} ${calloutdata.LastName}
-
-
- ${language.Location}
- ${calloutdata.StreetName ?? 'N/A'}
-
-
- ${language.Postal}
- ${calloutdata.Postal ?? 'N/A'}
-
-
-
-
- `);
-
- if (messagetype == "response") {
-
- // HTML
- $("#dispatch-message-prompt-container").append(`
-
-
- ${language.TrackUnitProposal}
-
- ${hotkeys.TrackUnit}
-
- `)
-
- }
-
- } else { // if (messagetype == "detach" || messagetype == "shift" || messagetype == "ambulance" || messagetype == "police" || messagetype == "taxi" || messagetype == "tow" etc...)
-
- // HTML
- $("#dispatch-message-prompt-container").empty().show().append(`
-
- `);
- }
-}
-
-function StartCountdownTimer(timeInMS) {
- var remainingTime = timeInMS / 1000; // Convert milliseconds to seconds
- const countdownMessage = `${language.NextDispatchMessage} ${remainingTime} ${language.Seconds}...`;
-
- $("#countdown-timer").html(`${wrapText(countdownMessage, 70)}`); // Wrap text with max 30 characters per line
-
- var timerInterval = setInterval(function() {
- remainingTime--;
-
- if (remainingTime >= 0) {
- $("#countdown-timer").html(`${wrapText(`${language.NextDispatchMessage} ${remainingTime} ${language.Seconds}...`, 70)}`); // Wrap text with max 30 characters per line
- } else {
- clearInterval(timerInterval);
- $("#countdown-timer").html(`${wrapText("Time's up!", 70)}`); // Wrap "Time's up!" with max 30 characters per line
- }
- }, 1000);
-}
-
-// HINTS
-
-function ToggleHotKeyHintPrompt(display, hotkeys, language, time) {
- if (display) {
- $("#hint-prompt-container").empty(); // clear previous data
- $("#hint-prompt-container").show();
-
- // HTML
- $("#hint-prompt-container").append(`
-
-
-
-
- ${language.Aim} + ${hotkeys.OrderOnKneesOrStandUp}
- ${language.OrderOnKneesOrStandUpExplanation}
-
-
- ${hotkeys.PullOver}
- ${language.PullOver}
-
-
- ${hotkeys.AcceptCallout}
- ${language.AcceptCallout}
-
-
- ${hotkeys.CompleteCallout}
- ${language.CompleteCallout}
-
-
- ${hotkeys.RadialMenu}
- ${language.RadialMenuExplanation}
-
-
- /${commands.StopTrackingUnit}
- ${language.StopTrackingUnitExplanation}
-
-
-
-
- `);
-
- // Auto-hide after elapsed time
- setTimeout(function() {
- $("#hint-prompt-container").hide();
- $.post(`https://${resourceName}/reallowPromptMessages`, JSON.stringify({}));
- }, time); // 10 seconds in milliseconds
- } else {
- $("#hint-prompt-container").empty();
- $("#hint-prompt-container").hide();
- }
-}
-
-// CALLOUTS (DISPATCH)
-
-function ToggleCalloutDisplayPrompt(display, hotkeys, language, time, calloutdata, serviceType) {
- var calloutDisplayPromptTime = (time / 1000); // in s
-
- if (display) {
- $("#callout-prompt-container").empty(); // clear previous data
- $("#callout-prompt-container").show();
-
- // HTML
- $("#callout-prompt-container").append(`
-
-
-
-
- ${language.Caller}
- ${calloutdata.FirstName} ${calloutdata.LastName}
-
-
- ${language.Location}
- ${calloutdata.StreetName ?? 'N/A'}
-
-
- ${language.Postal}
- ${calloutdata.Postal ?? 'N/A'}
-
-
- ${calloutdata.Description ?? 'N/A'}
-
-
-
-
- `);
-
- // Clear any existing countdown interval
- clearInterval(window.countdownInterval);
-
- // Initial countdown display
- const countdownMessage = `${calloutDisplayPromptTime} ${language.Seconds}...`;
- $("#callout-countdown-timer").html(countdownMessage);
-
- calloutDisplayPromptTime--;
-
- window.countdownInterval = setInterval(function() {
- if (calloutDisplayPromptTime > 0) {
- // Update countdown display
- const countdownMessage = `${calloutDisplayPromptTime} ${language.Seconds}...`;
- $("#callout-countdown-timer").html(countdownMessage);
-
- calloutDisplayPromptTime--;
- } else {
- clearInterval(window.countdownInterval);
- $("#callout-prompt-container").hide();
- $.post(`https://${resourceName}/calloutTimeout`, JSON.stringify({}));
- }
- }, 1000); // update every second
-
- } else {
- $("#callout-prompt-container").empty(); // clear previous data
- $("#callout-prompt-container").hide();
- }
-}
-
-function ToggleCalloutInterface(display, hotkeys, pedCount, vehicleCount, objectCount, propCount, fireCount, smokeCount, calloutdata, pedOriginalCount, vehOriginalCount, objOriginalCount, propOriginalCount, fireOriginalCount, smokeOriginalCount) {
- isDisplayingCalloutInterface = display;
- if (display) {
- $("#callout-interface-container").empty().removeClass('slideOutToLeft').addClass('slideInFromLeft'); // clear previous data
- $("#callout-interface-container").show();
-
- // HTML
- $("#callout-interface-container").append(`
- แฏฝ ${calloutdata.CalloutName}
-
-
- ${pedCount > 0 ? `
-
- โก ${language.InvolvedPedsRemaining}
- ${pedCount}/${pedOriginalCount}
- ` : ''}
- ${vehicleCount > 0 ? `
-
- โก ${language.InvolvedVehsRemaining}
- ${vehicleCount}/${vehOriginalCount}
- ` : ''}
- ${objectCount > 0 ? `
-
- โก ${language.InvolvedObjsRemaining}
- ${objectCount}/${objOriginalCount}
- ` : ''}
- ${propCount > 0 ? `
-
- โก ${language.InvolvedPropsRemaining}
- ${propCount}/${propOriginalCount}
- ` : ''}
- ${fireCount > 0 ? `
-
- โก ${language.ExtinguishAllFires}
- ${fireCount}/${fireOriginalCount}
- ` : ''}
- ${smokeCount > 0 ? `
-
- โก ${language.ClearAreaOfSmoke}
- ${smokeCount}/${smokeOriginalCount}
- ` : ''}
-
-
-
- ${language.Press} ${hotkeys.ToggleCalloutInfo} ${language.ToHideOrShow}
- `);
-
- } else {
- $("#callout-interface-container").empty(); // clear previous data
- $("#callout-interface-container").hide();
- $('#minimized-indicator').fadeOut(200); // Hide indicator when interface is completely closed
- }
-}
-
-
-function TogglePreCalloutInterface(display, hotkeys, calloutdata) {
- isDisplayingPreCalloutInterface = display;
- if (display) {
- $("#callout-pre-interface-container").empty().removeClass('slideOutToLeft').addClass('slideInFromLeft'); // clear previous data
- $("#callout-pre-interface-container").show();
-
- // HTML
- $("#callout-pre-interface-container").append(`
-
- แฏฝ
- ${wrapText(`${language.EmergencyCall} (${calloutdata?.CalloutName ?? 'N/A'})`, 40)}
-
-
-
-
-
-
- โก
- ${language.Caller}
- ${wrapText(`${calloutdata?.FirstName ?? 'N/A'} ${calloutdata?.LastName ?? 'N/A'}`, 70)}
-
-
-
-
- โก
- ${language.CallDescription}
- ${wrapText(calloutdata?.Description ?? 'N/A', 70)}
-
-
-
-
- โก
- ${language.Location}
- ${wrapText(calloutdata?.StreetName ?? 'N/A', 70)}
-
-
-
-
- โก
- ${language.Postal}
- ${wrapText(calloutdata?.Postal ?? 'N/A', 70)}
-
-
-
-
- โก
- ${language.CalloutUnitsRequired}
- ${wrapText(calloutdata?.CalloutUnitsRequired?.description ?? 'N/A', 70)}
-
-
-
-
- โก
- ${language.DispatchNote}
- ${wrapText(language.DispatchNoteResponseText, 70)}
-
-
-
-
-
- ${language.Press} ${hotkeys.ToggleCalloutInfo} ${language.ToHideOrShow}
- `);
-
- } else {
- $("#callout-pre-interface-container").empty(); // clear previous data
- $("#callout-pre-interface-container").hide();
- $('#minimized-indicator').fadeOut(200); // Hide indicator when interface is completely closed
- }
-}
-
-// WAYPOINTS
-
-let Waypoints = []
-
-// Cache DOM elements and values for better performance
-let waypointCache = {
- container: null,
- distanceElement: null,
- lastDistanceText: '',
- lastScaleX: -999,
- lastScaleY: -999,
- width: 0,
- height: 0,
- offsetWidth: 0,
- offsetHeight: 0,
- needsSizeRecalc: true
-};
-
-// Update window dimensions on resize
-window.addEventListener('resize', function() {
- waypointCache.width = window.innerWidth;
- waypointCache.height = window.innerHeight;
- waypointCache.needsSizeRecalc = true;
-});
-
-function UpdateWaypointPosition(scaleX, scaleY, distanceText) {
- let waypoint = Waypoints[0];
- if (waypoint == null) {
- $("#waypoint-container").hide();
- return;
- }
-
- // Initialize cache if needed
- if (!waypointCache.container) {
- waypointCache.container = document.getElementById('waypoint-container');
- waypointCache.distanceElement = document.getElementById('waypoint-distance');
- waypointCache.width = window.innerWidth;
- waypointCache.height = window.innerHeight;
- }
-
- // Show container if hidden
- if (waypointCache.container.style.display === 'none') {
- $("#waypoint-container").show();
- waypointCache.needsSizeRecalc = true;
- }
-
- // Only update distance text if it changed
- if (distanceText !== waypointCache.lastDistanceText) {
- waypointCache.distanceElement.innerHTML = `แฏฝ ${distanceText}`;
- waypointCache.lastDistanceText = distanceText;
- waypointCache.needsSizeRecalc = true;
- }
-
- // Recalculate size only when needed (text changed or first time)
- if (waypointCache.needsSizeRecalc) {
- let positionInfo = waypointCache.container.getBoundingClientRect();
- waypointCache.offsetWidth = positionInfo.width;
- waypointCache.offsetHeight = positionInfo.height;
- waypointCache.needsSizeRecalc = false;
- }
-
- // Only update position if it changed significantly (reduce jitter)
- const threshold = 0.001; // ~1 pixel change threshold
- if (Math.abs(scaleX - waypointCache.lastScaleX) > threshold ||
- Math.abs(scaleY - waypointCache.lastScaleY) > threshold) {
- waypointCache.container.style.left = ((waypointCache.width - waypointCache.offsetWidth) * scaleX) + "px";
- waypointCache.container.style.top = ((waypointCache.height - waypointCache.offsetHeight) * scaleY) + "px";
- waypointCache.lastScaleX = scaleX;
- waypointCache.lastScaleY = scaleY;
- }
-}
-
-function AddWaypoint(addOrRemove) {
- let element = document.getElementById('waypoint-container');
- if (addOrRemove) {
- Waypoints.push({ element: element });
- // Reset cache
- waypointCache.needsSizeRecalc = true;
- waypointCache.lastDistanceText = '';
- } else {
- $("#waypoint-container").hide();
- Waypoints = [];
- // Clear cache
- waypointCache.lastDistanceText = '';
- waypointCache.lastScaleX = -999;
- waypointCache.lastScaleY = -999;
- }
-}
-
-// ERS SELECTION MENU
-
-let escapeEventListenerAddedERSSelectionMenu = false;
-let menuSoundInstance = null;
-function ToggleERSSelectionMenu(display, permissions) {
- if (display) {
- const hasPoliceAccess = permissions.isPolice;
- const hasAmbulanceAccess = permissions.isAmbulance;
- const hasFireAccess = permissions.isFire;
- const hasTowAccess = permissions.isTow;
-
- fadeOutMenuMusic(menuSoundInstance)
- menuSoundInstance = PlayNUISound('generic-sounds', 'selectionmenu', 0.5);
-
- // HTML
- const modal = `
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ${language.PoliceDescription}
-
-
-
-
-
-
-
-
-
-
- ${language.AmbulanceDescription}
-
-
-
-
-
-
-
-
-
-
- ${language.FireDescription}
-
-
-
-
-
-
-
-
-
-
- ${language.TowDescription}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- `;
-
- // Add the modal to the page
- $('body').append(modal);
-
- // Initialize the modal with static backdrop and disabled keyboard interaction
- $('#ers-selection-modal').modal({
- backdrop: 'static',
- keyboard: false
- });
-
- // Show the modal
- $('#ers-selection-modal').modal('show');
-
- for (var i = 1; i <= 6; i++) {
- addSoundOnHoverEventListener('s-btn-' + i);
- }
-
- // Handle Escape key press only when the modal is open
- $('#ers-selection-modal').on('shown.bs.modal', function() {
- if (!escapeEventListenerAddedERSSelectionMenu) {
- $(document).on('keydown', function(event) {
- if (event.key === "Escape") {
- // Close the modal
- fadeOutMenuMusic(menuSoundInstance)
- $('#ers-selection-modal').modal('hide');
- // Trigger the same action as the "No" button click
- CancelServiceSelection();
- // Ensure the event doesn't propagate further
- event.stopPropagation();
- }
- });
- escapeEventListenerAddedERSSelectionMenu = true;
- }
- }).on('hidden.bs.modal', function() {
- // Remove the Escape key press event listener when the modal is closed
- $(document).off('keydown');
- escapeEventListenerAddedERSSelectionMenu = false;
- });
-
- } else {
- // Hide and remove the modal if display is false
- $('#ers-selection-modal').modal('hide').on('hidden.bs.modal', function () {
- fadeOutMenuMusic(menuSoundInstance)
- $(this).remove();
- });
- }
-}
-
-function CancelServiceSelection() {
- $.post(`https://${resourceName}/cancelServiceSelection`, JSON.stringify({}));
- $('#ers-selection-modal').modal('hide').on('hidden.bs.modal', function () {
- fadeOutMenuMusic(menuSoundInstance)
- $(this).data('bs.modal', null); // Remove data object
- $(this).remove(); // Remove the modal element from DOM
- });
-}
-
-function SelectService(serviceType) {
- $.post(`https://${resourceName}/selectedService`, JSON.stringify({
- service: serviceType
- }));
- $('#ers-selection-modal').modal('hide').on('hidden.bs.modal', function () {
- fadeOutMenuMusic(menuSoundInstance)
- $(this).data('bs.modal', null); // Remove data object
- $(this).remove(); // Remove the modal element from DOM
- });
-}
-
-function fadeOutMenuMusic(soundInstance) {
- if (soundInstance !== null) {
- soundInstance.fade(soundInstance.volume(), 0, 5000);
- setTimeout(function() {
- soundInstance.stop();
- }, 5000);
- }
-}
-
-let escapeEventListenerAddedERSGearnMenu = false;
-
-function DisplayGearMenu(display, locationData) {
- if (display) {
-
- fadeOutMenuMusic(menuSoundInstance);
- menuSoundInstance = PlayNUISound('generic-sounds', 'selectionmenu', 0.5);
-
- //HTML
- const modal = `
-
- `;
-
- // Add the modal to the page
- $('body').append(modal);
-
- var clothingOptions = locationData.ClothingData;
-
- function getBackgroundColour(serviceType) {
- switch (serviceType) {
- case 'police': return 'primary';
- case 'fire': return 'danger';
- case 'ambulance': return 'warning';
- case 'tow': return 'info';
- default: return 'secondary';
- }
- }
-
- let backgroundColour = getBackgroundColour(locationData.ServiceType);
-
- // Generate the HTML for each clothing option
- $.each(clothingOptions, function (key, v) {
- let locationDataJson = encodeURIComponent(JSON.stringify(locationData));
-
- // Minify
- $("#gear-options").append(` `);
-
- // HTML
- // $("#gear-options").append(`
- //
- //
- //
- //
- //
- // ${v.Description}
- //
- //
- //
- //
- //
- // `);
- });
-
- // Initialize the modal with static backdrop and disabled keyboard interaction
- $('#ers-gear-modal').modal({
- backdrop: 'static',
- keyboard: false
- });
-
- // Show the modal
- $('#ers-gear-modal').modal('show');
-
- for (var i = 0; i < clothingOptions.length; i++) {
- addSoundOnHoverEventListener('g-btn-' + i);
- }
-
- // Handle Escape key press only when the modal is open
- $('#ers-gear-modal').on('shown.bs.modal', function() {
- if (!escapeEventListenerAddedERSGearnMenu) {
- $(document).on('keydown', function(event) {
- if (event.key === "Escape") {
- // Close the modal
- fadeOutMenuMusic(menuSoundInstance);
- $('#ers-gear-modal').modal('hide');
- // Trigger the same action as the "No" button click
- CancelGearSelection();
- // Ensure the event doesn't propagate further
- event.stopPropagation();
- }
- });
- escapeEventListenerAddedERSGearnMenu = true;
- }
- }).on('hidden.bs.modal', function() {
- // Remove the Escape key press event listener when the modal is closed
- $(document).off('keydown');
- escapeEventListenerAddedERSGearnMenu = false;
- });
-
- } else {
- // Hide and remove the modal if display is false
- $('#ers-gear-modal').modal('hide').on('hidden.bs.modal', function () {
- fadeOutMenuMusic(menuSoundInstance);
- $(this).remove();
- });
- }
-}
-
-function handleClick(button) {
- let key = button.getAttribute('data-key');
- let locationDataJson = button.getAttribute('data-location-data');
- let locationData = JSON.parse(decodeURIComponent(locationDataJson));
- SelectedGear(key, locationData);
-}
-
-function SelectedGear(key, locationData) {
- $.post(`https://${resourceName}/selectedGear`, JSON.stringify({
- clothingIndex: key,
- locationData: locationData
- }));
- $('#ers-gear-modal').modal('hide').on('hidden.bs.modal', function () {
- fadeOutMenuMusic(menuSoundInstance);
- $(this).data('bs.modal', null); // Remove data object
- $(this).remove(); // Remove the modal element from DOM
- });
-}
-
-function CancelGearSelection() {
- $.post(`https://${resourceName}/cancelGearSelection`, JSON.stringify({}));
- $('#ers-gear-modal').modal('hide').on('hidden.bs.modal', function () {
- fadeOutMenuMusic(menuSoundInstance)
- $(this).data('bs.modal', null); // Remove data object
- $(this).remove(); // Remove the modal element from DOM
- });
-}
-
-///////////////////// UNIFIED PROMPT SYSTEM /////////////////////
-
-///////////////////// USER INTERFACE TOGGLE /////////////////////
-
-const containerIDs = {
- preCallout: "#callout-pre-interface-container",
- callout: "#callout-interface-container",
-};
-
-function slideOut(element) {
- $(element).removeClass('slideInFromLeft').addClass('slideOutToLeft');
- setTimeout(() => {
- $(element).hide();
- updateMinimizedIndicator();
- }, 300); // Match duration with animation
-}
-
-// Function to show the element with slide-in animation
-function slideIn(element) {
- $(element).show().removeClass('slideOutToLeft').addClass('slideInFromLeft');
- updateMinimizedIndicator();
-}
-
-function updateMinimizedIndicator() {
- const preCalloutHidden = isDisplayingPreCalloutInterface && !$(containerIDs.preCallout).is(':visible');
- const calloutHidden = isDisplayingCalloutInterface && !$(containerIDs.callout).is(':visible');
-
- // Show indicator if any interface is hidden
- if (preCalloutHidden || calloutHidden) {
- $('#minimized-indicator').fadeIn(200);
- } else {
- $('#minimized-indicator').fadeOut(200);
- }
-}
-
-function toggleCalloutInfo() {
- // Toggle pre-callout interface based on its initial state
- if (isDisplayingPreCalloutInterface) {
- const preCalloutElement = containerIDs.preCallout;
- if ($(preCalloutElement).is(':visible')) {
- slideOut(preCalloutElement);
- } else {
- slideIn(preCalloutElement);
- }
- }
-
- // Toggle callout interface based on its initial state
- if (isDisplayingCalloutInterface) {
- const calloutElement = containerIDs.callout;
- if ($(calloutElement).is(':visible')) {
- slideOut(calloutElement);
- } else {
- slideIn(calloutElement);
- }
- }
-}
-
-// Click handler for minimized indicator
-document.addEventListener('DOMContentLoaded', function() {
- const minimizedIndicator = document.getElementById('minimized-indicator');
- if (minimizedIndicator) {
- minimizedIndicator.addEventListener('click', function() {
- toggleCalloutInfo();
- });
- }
-});
-
-///////////////////// CALLOUT UNIT WAYPOINTS /////////////////////
-
-function updateWaypoints(data) {
- const waypointData = data.data;
- const existingWaypoints = trackExistingUnitWaypoints();
- for (const [key, value] of Object.entries(waypointData)) {
- if (value !== null) {
- if (value.distanceText > 0) {
- processUnitWaypoint(key, value, existingWaypoints);
- }
- }
- }
- removeUnusedUnitWaypoints(existingWaypoints);
-}
-
-function trackExistingUnitWaypoints() {
- const existingWaypoints = new Set();
- document.querySelectorAll('.unit-waypoint-container').forEach(container => {
- existingWaypoints.add(container.id);
- });
- return existingWaypoints;
-}
-
-function processUnitWaypoint(key, value, existingWaypoints) {
- const waypointId = `unit-waypoint-container-${key}`;
- let waypointContainer = document.getElementById(waypointId);
-
- if (!waypointContainer) {
- waypointContainer = createUnitWaypointContainer(waypointId);
- }
-
- updateUnitWaypointPosition(waypointContainer, value);
- updateUnitWaypointContent(waypointContainer, value);
-
- existingWaypoints.delete(waypointId);
-}
-
-function createUnitWaypointContainer(waypointId) {
- const waypointContainer = document.createElement('div');
- waypointContainer.classList.add('unit-waypoint-container', 'smooth-transition');
- waypointContainer.id = waypointId;
- document.body.appendChild(waypointContainer);
- return waypointContainer;
-}
-
-function updateUnitWaypointPosition(container, value) {
- const width = window.innerWidth;
- const height = window.innerHeight;
- const positionInfo = container.getBoundingClientRect();
- const offsetWidth = positionInfo.width;
- const offsetHeight = positionInfo.height;
-
- if (value.scaleX >= 0 && value.scaleX <= 1 && value.scaleY >= 0 && value.scaleY <= 1) {
- container.style.left = ((width - offsetWidth) * value.scaleX) + "px";
- container.style.top = ((height - offsetHeight) * value.scaleY) + "px";
- }
-}
-
-function updateUnitWaypointContent(container, value) {
- container.innerHTML = `
- แฏฝ ${value.distanceText}${value.metrics}
- `;
-}
-
-function removeUnusedUnitWaypoints(existingWaypoints) {
- existingWaypoints.forEach(id => {
- const container = document.getElementById(id);
- if (container) {
- container.remove();
- }
- });
-}
-
-///////////////////// QUESTIONING /////////////////////
-
-function ToggleQuestionsModule(display, questions) {
- if (display) {
- $("#question-options-list").empty();
- $("#ped-interaction-questioning").show();
-
- if (questions.length > 0) {
-
- // Render the questions in a column with spacing
- let html = `
+ `),applySavedPosition("dispatch-message-prompt-container");return}"response"==a||"arrival"==a?("response"==a&&$.post(`https://${resourceName}/offerToTrackPlayer`,JSON.stringify({calloutdata:n})),$("#dispatch-message-prompt-container").empty().show().append(` ${wrapText(i,50)}
${language.Caller} ${wrapText(`${n.FirstName} ${n.LastName}`,50)} ${language.CallDescription} ${wrapText(n.Description??"N/A",50)} ${language.Location} ${wrapText(n.StreetName??"N/A",50)} ${language.Postal} ${wrapText(n.Postal??"N/A",50)} ${language.CalloutUnitsRequired} ${wrapText(n.CalloutUnitsRequired?.description??"N/A",50)} ${language.DispatchNote} ${wrapText(language.DispatchNoteResponseText??"N/A",50)}
`),applySavedPosition("dispatch-message-prompt-container"),"response"==a&&$("#dispatch-message-prompt-container").append(` `)):($("#dispatch-message-prompt-container").empty().show().append(` `),applySavedPosition("dispatch-message-prompt-container"))}function StartCountdownTimer(e){var t=e/1e3;let a=`${language.NextDispatchMessage} ${t} ${language.Seconds}...`;$("#countdown-timer").html(`${wrapText(a,70)}
`);var n=setInterval(function(){--t>=0?$("#countdown-timer").html(`${wrapText(`${language.NextDispatchMessage} ${t} ${language.Seconds}...`,70)}
`):(clearInterval(n),$("#countdown-timer").html(`${wrapText("Time's up!",70)}
`))},1e3)}function ToggleHotKeyHintPrompt(e,t,a,n){e?($("#hint-prompt-container").empty(),$("#hint-prompt-container").show(),applySavedPosition("hint-prompt-container"),$("#hint-prompt-container").append(` ${a.HotKeys} ${a.Aim} + ${t.OrderOnKneesOrStandUp} ${t.PullOver} ${t.AcceptCallout} ${t.CompleteCallout} ${t.RadialMenu} /${commands.StopTrackingUnit} ${a.Explanation} ${a.OrderOnKneesOrStandUpExplanation} ${a.PullOver} ${a.AcceptCallout} ${a.CompleteCallout} ${a.RadialMenuExplanation} ${a.StopTrackingUnitExplanation}
`),setTimeout(function(){$("#hint-prompt-container").hide(),$.post(`https://${resourceName}/reallowPromptMessages`,JSON.stringify({}))},n)):($("#hint-prompt-container").empty(),$("#hint-prompt-container").hide())}function SelectBackGroundColourByServiceType(e){var t="bg-primary",a="border-primary",n="btn-outline-primary",i="text-light";return"police"==e?(t="bg-primary",a="border-primary",n="btn-outline-primary",i="text-light"):"ambulance"==e?(t="bg-success",a="border-success",n="btn-outline-success",i="text-light"):"fire"==e?(t="bg-danger",a="border-danger",n="btn-outline-danger",i="text-light"):"tow"==e&&(t="bg-warning",a="border-warning",n="btn-outline-warning",i="text-light"),{backgroundColor:t,borderColor:a,textColor:i,buttonOutlineColor:n}}function ToggleCalloutDisplayPrompt(e,t,a,n,i,o){var s=n/1e3,{backgroundColor:l,borderColor:r,textColor:c,buttonOutlineColor:d}=SelectBackGroundColourByServiceType(o);e?($("#callout-prompt-container").empty(),$("#callout-prompt-container").show(),$("#callout-prompt-container").append(` ${a.Caller} ${wrapText(`${i.FirstName} ${i.LastName}`,50)} ${a.CallDescription} ${wrapText(i.Description??"N/A",50)} ${a.Location} ${wrapText(i.StreetName??"N/A",50)} ${a.Postal} ${wrapText(i.Postal??"N/A",50)} ${a.CalloutUnitsRequired} ${wrapText(i.CalloutUnitsRequired?.description??"N/A",50)} ${a.DispatchNote} ${wrapText(a.DispatchNoteResponseText??"N/A",50)}
`),applySavedPosition("callout-prompt-container"),clearInterval(window.countdownInterval),s--,window.countdownInterval=setInterval(function(){s>0?($("#callout-prompt-container").find("#countdown-text").html(` ${a.TimeRemainingToAcceptCallout} ${s} ${a.Seconds}... `),s--):(clearInterval(window.countdownInterval),$("#callout-prompt-container").hide(),$.post(`https://${resourceName}/calloutTimeout`,JSON.stringify({})))},1e3)):($("#callout-prompt-container").empty(),$("#callout-prompt-container").hide())}function ToggleCalloutInterface(e,t,a,n,i,o,s,l,r,c,d,u,g,p,b){isDisplayingCalloutInterface=e,e?($("#callout-interface-container").empty().addClass("slideInFromLeft"),$("#callout-interface-container").show(),$("#callout-interface-container").append(` แฏฝ ${r.CalloutName} ${a>0?` โก ${language.InvolvedPedsRemaining} ${a}/${c} `:""} ${n>0?` โก ${language.InvolvedVehsRemaining} ${n}/${d} `:""} ${i>0?` โก ${language.InvolvedObjsRemaining} ${i}/${u} `:""} ${o>0?` โก ${language.InvolvedPropsRemaining} ${o}/${g} `:""} ${s>0?` โก ${language.ExtinguishAllFires} ${s}/${p} `:""} ${l>0?` โก ${language.ClearAreaOfSmoke} ${l}/${b} `:""}
${language.Press} ${t.ToggleCalloutInfo} ${language.ToHideOrShow}
`),applySavedPosition("callout-interface-container")):($("#callout-interface-container").empty(),$("#callout-interface-container").hide())}function TogglePreCalloutInterface(e,t,a){isDisplayingPreCalloutInterface=e,e?($("#callout-pre-interface-container").empty().addClass("slideInFromLeft"),$("#callout-pre-interface-container").show(),$("#callout-pre-interface-container").append(` แฏฝ ${wrapText(`${language.EmergencyCall} (${a?.CalloutName??"N/A"})`,40)} โก ${language.Caller} ${wrapText(`${a?.FirstName??"N/A"} ${a?.LastName??"N/A"}`,70)} โก ${language.CallDescription} ${wrapText(a?.Description??"N/A",70)} โก ${language.Location} ${wrapText(a?.StreetName??"N/A",70)} โก ${language.Postal} ${wrapText(a?.Postal??"N/A",70)} โก ${language.CalloutUnitsRequired} ${wrapText(a?.CalloutUnitsRequired?.description??"N/A",70)} โก ${language.DispatchNote} ${wrapText(language.DispatchNoteResponseText,70)}
${language.Press} ${t.ToggleCalloutInfo} ${language.ToHideOrShow}
`),applySavedPosition("callout-pre-interface-container")):($("#callout-pre-interface-container").empty(),$("#callout-pre-interface-container").hide())}let Waypoints=[];function UpdateWaypointPosition(e,t,a){if(null==Waypoints[0]){$("#waypoint-container").hide();return}let n=document.getElementById("waypoint-container");$("#waypoint-distance").empty(),$("#waypoint-container").show(),$("#waypoint-distance").append(`
+ แฏฝ ${a}
+ `);let i=window.innerWidth,o=window.innerHeight,s=n.getBoundingClientRect(),l=s.width,r=s.height;n.style.left=(i-l)*e+"px",n.style.top=(o-r)*t+"px"}function AddWaypoint(e){let t=document.getElementById("waypoint-container");e?Waypoints.push({element:t}):($("#waypoint-container").hide(),Waypoints=[])}let escapeEventListenerAddedERSSelectionMenu=!1,menuSoundInstance=null;function ToggleERSSelectionMenu(e,t){if(e){let a=t.isPolice,n=t.isAmbulance,i=t.isFire,o=t.isTow;fadeOutMenuMusic(menuSoundInstance),menuSoundInstance=PlayNUISound("generic-sounds","selectionmenu",.5);let s=` ${language.PoliceDescription}
${language.AmbulanceDescription}
${language.FireDescription}
${language.TowDescription}
`;$("body").append(s),$("#ers-selection-modal").modal({backdrop:"static",keyboard:!1}),$("#ers-selection-modal").modal("show");for(var l=1;l<=6;l++)addSoundOnHoverEventListener("s-btn-"+l);$("#ers-selection-modal").on("shown.bs.modal",function(){escapeEventListenerAddedERSSelectionMenu||($(document).on("keydown",function(e){"Escape"===e.key&&(fadeOutMenuMusic(menuSoundInstance),$("#ers-selection-modal").modal("hide"),CancelServiceSelection(),e.stopPropagation())}),escapeEventListenerAddedERSSelectionMenu=!0)}).on("hidden.bs.modal",function(){$(document).off("keydown"),escapeEventListenerAddedERSSelectionMenu=!1})}else $("#ers-selection-modal").modal("hide").on("hidden.bs.modal",function(){fadeOutMenuMusic(menuSoundInstance),$(this).remove()})}function CancelServiceSelection(){$.post(`https://${resourceName}/cancelServiceSelection`,JSON.stringify({})),$("#ers-selection-modal").modal("hide").on("hidden.bs.modal",function(){fadeOutMenuMusic(menuSoundInstance),$(this).data("bs.modal",null),$(this).remove()})}function SelectService(e){$.post(`https://${resourceName}/selectedService`,JSON.stringify({service:e})),$("#ers-selection-modal").modal("hide").on("hidden.bs.modal",function(){fadeOutMenuMusic(menuSoundInstance),$(this).data("bs.modal",null),$(this).remove()})}function fadeOutMenuMusic(e){null!==e&&(e.fade(e.volume(),0,5e3),setTimeout(function(){e.stop()},5e3))}let escapeEventListenerAddedERSGearnMenu=!1;function DisplayGearMenu(e,t){if(e){fadeOutMenuMusic(menuSoundInstance),menuSoundInstance=PlayNUISound("generic-sounds","selectionmenu",.5);let a=` `;$("body").append(a);var n=t.ClothingData;let i=function e(t){switch(t){case"police":return"primary";case"fire":return"danger";case"ambulance":return"warning";case"tow":return"info";default:return"secondary"}}(t.ServiceType);$.each(n,function(e,a){let n=encodeURIComponent(JSON.stringify(t));$("#gear-options").append(` `)}),$("#ers-gear-modal").modal({backdrop:"static",keyboard:!1}),$("#ers-gear-modal").modal("show");for(var o=0;o$(e).hide(),250)}function slideIn(e){$(e).show().removeClass("slideOutToLeft").addClass("slideInFromLeft")}function toggleCalloutInfo(){if(isDisplayingPreCalloutInterface){let e=containerIDs.preCallout;$(e).is(":visible")?slideOut(e):slideIn(e)}if(isDisplayingCalloutInterface){let t=containerIDs.callout;$(t).is(":visible")?slideOut(t):slideIn(t)}}function updateWaypoints(e){let t=e.data,a=trackExistingUnitWaypoints();for(let[n,i]of Object.entries(t))null!==i&&i.distanceText>0&&processUnitWaypoint(n,i,a);removeUnusedUnitWaypoints(a)}function trackExistingUnitWaypoints(){let e=new Set;return document.querySelectorAll(".unit-waypoint-container").forEach(t=>{e.add(t.id)}),e}function processUnitWaypoint(e,t,a){let n=`unit-waypoint-container-${e}`,i=document.getElementById(n);i||(i=createUnitWaypointContainer(n)),updateUnitWaypointPosition(i,t),updateUnitWaypointContent(i,t),a.delete(n)}function createUnitWaypointContainer(e){let t=document.createElement("div");return t.classList.add("unit-waypoint-container","smooth-transition"),t.id=e,document.body.appendChild(t),t}function updateUnitWaypointPosition(e,t){let a=window.innerWidth,n=window.innerHeight,i=e.getBoundingClientRect(),o=i.width,s=i.height;t.scaleX>=0&&t.scaleX<=1&&t.scaleY>=0&&t.scaleY<=1&&(e.style.left=(a-o)*t.scaleX+"px",e.style.top=(n-s)*t.scaleY+"px")}function updateUnitWaypointContent(e,t){e.innerHTML=`
+ แฏฝ ${t.distanceText}${t.metrics}
+ `}function removeUnusedUnitWaypoints(e){e.forEach(e=>{let t=document.getElementById(e);t&&t.remove()})}function ToggleQuestionsModule(e,t){if(e){if($("#question-options-list").empty(),$("#ped-interaction-questioning").show(),t.length>0){let a=`
- ${questions.map((q, index) => `
+ ${t.map((e,t)=>`
- ${wrapText(q.text, 30)}
+ ${wrapText(e.text,30)}
- `).join('')}
+ `).join("")}
- `;
- $("#question-options-list").append(html);
-
- // Add sound effects to the question buttons
- questions.forEach((_, index) => {
- const buttonId = `s-btn-${index + 1}`;
- if (document.getElementById(buttonId)) {
- addSoundOnHoverEventListener(buttonId);
- }
- });
-
- // Add click handlers
- $("#question-options-list button").off("click").on("click", function() {
- let target = $(this).data("target");
- let questionText = $(this).data("question-text");
- let soundFile = $(this).data("sound-file");
- let soundVolume = $(this).data("sound-volume");
- if (target) {
- // Find the full question data for this button
- const selectedQuestion = {
- id: target,
- text: questionText,
- soundFile: soundFile,
- soundVolume: soundVolume
- };
-
- PlayNUISound('generic-sounds', "q_select", 1.0);
-
- $.post(`https://${resourceName}/questionSelected`, JSON.stringify({
- questionData: selectedQuestion
- }));
- }
- });
- }
-
- // Leave button
- let leaveBtn = `
+ `;$("#question-options-list").append(a),applySavedPosition("ped-interaction-questioning"),t.forEach((e,t)=>{let a=`s-btn-${t+1}`;document.getElementById(a)&&addSoundOnHoverEventListener(a)}),$("#question-options-list button").off("click").on("click",function(){let e=$(this).data("target"),t=$(this).data("question-text"),a=$(this).data("sound-file"),n=$(this).data("sound-volume");e&&(PlayNUISound("generic-sounds","q_select",1),$.post(`https://${resourceName}/questionSelected`,JSON.stringify({questionData:{id:e,text:t,soundFile:a,soundVolume:n}})))})}let n=`
${language.ExitConversation}
- `;
- $("#question-leave-btn").html(leaveBtn);
-
- // Add sound effect to leave button
- if (document.getElementById("leave-questioning-btn")) {
- addSoundOnHoverEventListener("leave-questioning-btn");
- }
-
- // Add click handler for leave button
- $("#leave-questioning-btn").off("click").on("click", function() {
- PlayNUISound('generic-sounds', "radialclose", 0.5);
- $.post(`https://${resourceName}/leaveQuestioning`, JSON.stringify({}));
- });
-
- } else {
- $("#ped-interaction-questioning").hide();
- $("#question-options-list").empty();
- $("#question-leave-btn").empty();
- }
-}
-
-function UpdateAnswers(display, answers) {
- if (display) {
- // Get the answers container and clear it
- let answersContainer = $("#question-answers-list");
-
- // Clear the answers container
- answersContainer.empty();
-
- // Add a title above the answers
- answersContainer.html(`
+ `;$("#question-leave-btn").html(n),document.getElementById("leave-questioning-btn")&&addSoundOnHoverEventListener("leave-questioning-btn"),$("#leave-questioning-btn").off("click").on("click",function(){PlayNUISound("generic-sounds","radialclose",.5),$.post(`https://${resourceName}/leaveQuestioning`,JSON.stringify({}))})}else $("#ped-interaction-questioning").hide(),$("#question-options-list").empty(),$("#question-leave-btn").empty()}function UpdateAnswers(e,t){if(e){let a=$("#question-answers-list");a.empty(),a.html(`